diff --git a/.emacs-project b/.emacs-project new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..923b697 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.bundle +db/*.sqlite3 +log/*.log +tmp/ +.sass-cache/ diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..53607ea --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--colour diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..905a319 --- /dev/null +++ b/Gemfile @@ -0,0 +1,39 @@ +source 'http://rubygems.org' + +gem 'rails', '3.1.1' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' + + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', '~> 3.1.4' + gem 'coffee-rails', '~> 3.1.1' + gem 'uglifier', '>= 1.0.3' +end + +gem 'jquery-rails' +gem 'inherited_resources' +gem 'simple_form' + +group :development, :test do + gem 'rspec-rails', :require => 'rspec/rails' + gem 'rspec-given', :require => 'rspec/given' +end + +# To use ActiveModel has_secure_password +# gem 'bcrypt-ruby', '~> 3.0.0' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug19', :require => 'ruby-debug' + diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..764c313 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,142 @@ +GEM + remote: http://rubygems.org/ + specs: + actionmailer (3.1.1) + actionpack (= 3.1.1) + mail (~> 2.3.0) + actionpack (3.1.1) + activemodel (= 3.1.1) + activesupport (= 3.1.1) + builder (~> 3.0.0) + erubis (~> 2.7.0) + i18n (~> 0.6) + rack (~> 1.3.2) + rack-cache (~> 1.1) + rack-mount (~> 0.8.2) + rack-test (~> 0.6.1) + sprockets (~> 2.0.2) + activemodel (3.1.1) + activesupport (= 3.1.1) + builder (~> 3.0.0) + i18n (~> 0.6) + activerecord (3.1.1) + activemodel (= 3.1.1) + activesupport (= 3.1.1) + arel (~> 2.2.1) + tzinfo (~> 0.3.29) + activeresource (3.1.1) + activemodel (= 3.1.1) + activesupport (= 3.1.1) + activesupport (3.1.1) + multi_json (~> 1.0) + arel (2.2.1) + builder (3.0.0) + coffee-rails (3.1.1) + coffee-script (>= 2.2.0) + railties (~> 3.1.0) + coffee-script (2.2.0) + coffee-script-source + execjs + coffee-script-source (1.2.0) + diff-lcs (1.1.3) + erubis (2.7.0) + execjs (1.3.0) + multi_json (~> 1.0) + has_scope (0.5.1) + hike (1.2.1) + i18n (0.6.0) + inherited_resources (1.3.0) + has_scope (~> 0.5.0) + responders (~> 0.6.0) + jquery-rails (1.0.19) + railties (~> 3.0) + thor (~> 0.14) + json (1.6.5) + mail (2.3.0) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.17.2) + multi_json (1.0.4) + polyglot (0.3.3) + rack (1.3.6) + rack-cache (1.1) + rack (>= 0.4) + rack-mount (0.8.3) + rack (>= 1.0.0) + rack-ssl (1.3.2) + rack + rack-test (0.6.1) + rack (>= 1.0) + rails (3.1.1) + actionmailer (= 3.1.1) + actionpack (= 3.1.1) + activerecord (= 3.1.1) + activeresource (= 3.1.1) + activesupport (= 3.1.1) + bundler (~> 1.0) + railties (= 3.1.1) + railties (3.1.1) + actionpack (= 3.1.1) + activesupport (= 3.1.1) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (~> 0.14.6) + rake (0.9.2.2) + rdoc (3.12) + json (~> 1.4) + responders (0.6.4) + rspec (2.8.0) + rspec-core (~> 2.8.0) + rspec-expectations (~> 2.8.0) + rspec-mocks (~> 2.8.0) + rspec-core (2.8.0) + rspec-expectations (2.8.0) + diff-lcs (~> 1.1.2) + rspec-given (1.4.2) + rspec (> 1.2.8) + rspec-mocks (2.8.0) + rspec-rails (2.8.1) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec (~> 2.8.0) + sass (3.1.12) + sass-rails (3.1.5) + actionpack (~> 3.1.0) + railties (~> 3.1.0) + sass (~> 3.1.10) + tilt (~> 1.3.2) + simple_form (1.5.2) + actionpack (~> 3.0) + activemodel (~> 3.0) + sprockets (2.0.3) + hike (~> 1.2) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + sqlite3 (1.3.5) + thor (0.14.6) + tilt (1.3.3) + treetop (1.4.10) + polyglot + polyglot (>= 0.3.1) + tzinfo (0.3.31) + uglifier (1.2.2) + execjs (>= 0.3.0) + multi_json (>= 1.0.2) + +PLATFORMS + ruby + +DEPENDENCIES + coffee-rails (~> 3.1.1) + inherited_resources + jquery-rails + rails (= 3.1.1) + rspec-given + rspec-rails + sass-rails (~> 3.1.4) + simple_form + sqlite3 + uglifier (>= 1.0.3) diff --git a/README b/README new file mode 100644 index 0000000..7c36f23 --- /dev/null +++ b/README @@ -0,0 +1,261 @@ +== Welcome to Rails + +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. + +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. + +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. + +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. + + +== Getting Started + +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) + +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) + +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" + +4. Follow the guidelines to start developing your application. You can find +the following resources handy: + +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: + +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two books will bring you up to speed on the Ruby language and also on +programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.all + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. + +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.org/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- assets + | |-- images + | |-- javascripts + | `-- stylesheets + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + |-- assets + `-- stylesheets + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/assets + Contains subdirectories for images, stylesheets, and JavaScript files. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..fcb53d8 --- /dev/null +++ b/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Elo::Application.load_tasks diff --git a/app/assets/images/rails.png b/app/assets/images/rails.png new file mode 100644 index 0000000..d5edc04 Binary files /dev/null and b/app/assets/images/rails.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000..37c7bfc --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,9 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/app/assets/javascripts/games.js.coffee b/app/assets/javascripts/games.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/games.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/players.js.coffee b/app/assets/javascripts/players.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/players.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000..fc25b57 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,7 @@ +/* + * This is a manifest file that'll automatically include all the stylesheets available in this directory + * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at + * the top of the compiled file, but it's generally better to create a new file per style scope. + *= require_self + *= require_tree . +*/ \ No newline at end of file diff --git a/app/assets/stylesheets/games.css.scss b/app/assets/stylesheets/games.css.scss new file mode 100644 index 0000000..db1b7bc --- /dev/null +++ b/app/assets/stylesheets/games.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the games controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/players.css.scss b/app/assets/stylesheets/players.css.scss new file mode 100644 index 0000000..c4f674b --- /dev/null +++ b/app/assets/stylesheets/players.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the players controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000..e8065d9 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery +end diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb new file mode 100644 index 0000000..fc2a42f --- /dev/null +++ b/app/controllers/games_controller.rb @@ -0,0 +1,13 @@ +class GamesController < InheritedResources::Base + def create + super do |format| + format.html { redirect_to players_path } + end + end + + def destroy + super do |format| + format.html { redirect_to players_path } + end + end +end diff --git a/app/controllers/players_controller.rb b/app/controllers/players_controller.rb new file mode 100644 index 0000000..7179d6a --- /dev/null +++ b/app/controllers/players_controller.rb @@ -0,0 +1,19 @@ +class PlayersController < InheritedResources::Base + def create + super do |format| + format.html { redirect_to players_path } + end + end + + def update + super do |format| + format.html { redirect_to players_path } + end + end + + private + + def collection + @players ||= Player.by_rank + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/helpers/games_helper.rb b/app/helpers/games_helper.rb new file mode 100644 index 0000000..2ef8c1f --- /dev/null +++ b/app/helpers/games_helper.rb @@ -0,0 +1,2 @@ +module GamesHelper +end diff --git a/app/helpers/players_helper.rb b/app/helpers/players_helper.rb new file mode 100644 index 0000000..e8f775c --- /dev/null +++ b/app/helpers/players_helper.rb @@ -0,0 +1,2 @@ +module PlayersHelper +end diff --git a/app/mailers/.gitkeep b/app/mailers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/.gitkeep b/app/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/game.rb b/app/models/game.rb new file mode 100644 index 0000000..642ef5f --- /dev/null +++ b/app/models/game.rb @@ -0,0 +1,13 @@ +class Game < ActiveRecord::Base + belongs_to :winner, :class_name => "Player" + belongs_to :loser, :class_name => "Player" + + before_create :update_ranks + + private + + def update_ranks + winner.wins!(loser) + loser.loses!(winner) + end +end diff --git a/app/models/player.rb b/app/models/player.rb new file mode 100644 index 0000000..69caef0 --- /dev/null +++ b/app/models/player.rb @@ -0,0 +1,37 @@ +class Player < ActiveRecord::Base + + validates_uniqueness_of :email + validates_presence_of :email + + has_many :wins, :class_name => "Game", :foreign_key => :winner_id, :dependent => :destroy + has_many :loses, :class_name => "Game", :foreign_key => :loser_id, :dependent => :destroy + + def display_name + name.blank? ? email : name + end + + def self.by_rank + order('rank desc') + end + + def games + (wins + loses).sort_by(&:created_at) + end + + def new_rank(opponent_rank, score) + rank + (K_RATING_COEFFICIENT*(score - win_expectancy(rank - opponent_rank))).round + end + + def win_expectancy(diff) + 1 / ( 10**(-diff.to_f/F_RATING_INTERVAL_SCALE_WEIGHT.to_f) + 1) + end + + def wins!(opponent) + update_attributes!(:rank => new_rank(opponent.rank, 1)) + end + + def loses!(opponent) + update_attributes!(:rank => new_rank(opponent.rank, 0)) + end + +end diff --git a/app/views/games/new.html.erb b/app/views/games/new.html.erb new file mode 100644 index 0000000..d0046b0 --- /dev/null +++ b/app/views/games/new.html.erb @@ -0,0 +1,6 @@ +

New Game

+<%= simple_form_for @game do |f| %> +<%= f.association :winner %> +<%= f.association :loser %> +<%= f.submit %> +<% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000..ee0c492 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + Elo + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application" %> + <%= csrf_meta_tags %> + + + +<%= yield %> + + + diff --git a/app/views/players/_form.html.erb b/app/views/players/_form.html.erb new file mode 100644 index 0000000..cde6a04 --- /dev/null +++ b/app/views/players/_form.html.erb @@ -0,0 +1,6 @@ +<%= simple_form_for @player do |f| %> +<%= f.input :email %> +<%= f.input :name, :required => false %> +<%= f.input :rank, :hint => "Initial novice rating is 250" %> +<%= f.submit 'Submit' %> +<% end -%> diff --git a/app/views/players/edit.html.erb b/app/views/players/edit.html.erb new file mode 100644 index 0000000..51e9c9e --- /dev/null +++ b/app/views/players/edit.html.erb @@ -0,0 +1,16 @@ +

<%= @player.display_name %>

+<%= render :partial => "form" %> + +

Games

+<% if @player.games.count == 0 %> +

No games played yet

+<% else -%> +
    +<% @player.games.each do |game| -%> +
  • <%= game.winner.display_name %> beat +<%= game.loser.display_name %> +on <%= game.created_at %> +(<%= link_to "X", game_path(game), :method => :delete %>) +
  • +<% end -%> +<% end -%> diff --git a/app/views/players/index.html.erb b/app/views/players/index.html.erb new file mode 100644 index 0000000..b8432bc --- /dev/null +++ b/app/views/players/index.html.erb @@ -0,0 +1,10 @@ +

    Players

    +
      + <% @players.each do |player| -%> +
    • <%= link_to player.display_name, edit_player_path(player) %> + (<%= player.rank %>)(<%= link_to 'X', player_path(player), :method => :delete, :confirm => "Delete #{player.display_name}?" %>)
    • +<% end -%> +
    + +<%= link_to 'New Player', new_player_path %> +<%= link_to 'New Game', new_game_path %> diff --git a/app/views/players/new.html.erb b/app/views/players/new.html.erb new file mode 100644 index 0000000..dde5820 --- /dev/null +++ b/app/views/players/new.html.erb @@ -0,0 +1,2 @@ +

    New Player

    +<%= render :partial => 'form' %> diff --git a/bin/autospec b/bin/autospec new file mode 100755 index 0000000..64dcb9c --- /dev/null +++ b/bin/autospec @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'autospec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rspec-core', 'autospec') diff --git a/bin/erubis b/bin/erubis new file mode 100755 index 0000000..2c7348b --- /dev/null +++ b/bin/erubis @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'erubis' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('erubis', 'erubis') diff --git a/bin/htmldiff b/bin/htmldiff new file mode 100755 index 0000000..c70e238 --- /dev/null +++ b/bin/htmldiff @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'htmldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('diff-lcs', 'htmldiff') diff --git a/bin/ldiff b/bin/ldiff new file mode 100755 index 0000000..8e3524a --- /dev/null +++ b/bin/ldiff @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'ldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('diff-lcs', 'ldiff') diff --git a/bin/rackup b/bin/rackup new file mode 100755 index 0000000..8cc9953 --- /dev/null +++ b/bin/rackup @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rackup' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rack', 'rackup') diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..daa4a39 --- /dev/null +++ b/bin/rails @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rails' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rails', 'rails') diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..26c7a2d --- /dev/null +++ b/bin/rake @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rake', 'rake') diff --git a/bin/rake2thor b/bin/rake2thor new file mode 100755 index 0000000..b0b6ec9 --- /dev/null +++ b/bin/rake2thor @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rake2thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('thor', 'rake2thor') diff --git a/bin/rdoc b/bin/rdoc new file mode 100755 index 0000000..f57260f --- /dev/null +++ b/bin/rdoc @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rdoc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rdoc', 'rdoc') diff --git a/bin/ri b/bin/ri new file mode 100755 index 0000000..90f2517 --- /dev/null +++ b/bin/ri @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'ri' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rdoc', 'ri') diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..0c86b5c --- /dev/null +++ b/bin/rspec @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('rspec-core', 'rspec') diff --git a/bin/sass b/bin/sass new file mode 100755 index 0000000..d65bb10 --- /dev/null +++ b/bin/sass @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'sass' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('sass', 'sass') diff --git a/bin/sass-convert b/bin/sass-convert new file mode 100755 index 0000000..ddde743 --- /dev/null +++ b/bin/sass-convert @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'sass-convert' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('sass', 'sass-convert') diff --git a/bin/scss b/bin/scss new file mode 100755 index 0000000..9f5e435 --- /dev/null +++ b/bin/scss @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'scss' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('sass', 'scss') diff --git a/bin/thor b/bin/thor new file mode 100755 index 0000000..8421e00 --- /dev/null +++ b/bin/thor @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('thor', 'thor') diff --git a/bin/tilt b/bin/tilt new file mode 100755 index 0000000..09fe73e --- /dev/null +++ b/bin/tilt @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'tilt' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('tilt', 'tilt') diff --git a/bin/tt b/bin/tt new file mode 100755 index 0000000..6e3920b --- /dev/null +++ b/bin/tt @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'tt' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('treetop', 'tt') diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..e383adb --- /dev/null +++ b/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Elo::Application diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 0000000..87c2e52 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,54 @@ +require File.expand_path('../boot', __FILE__) + +# Pick the frameworks you want: +require "active_record/railtie" +require "action_controller/railtie" +require "action_mailer/railtie" +require "active_resource/railtie" +require "sprockets/railtie" +# require "rails/test_unit/railtie" + +if defined?(Bundler) + # If you precompile assets before deploying to production, use this line + Bundler.require(*Rails.groups(:assets => %w(development test))) + # If you want your assets lazily compiled in production, use this line + # Bundler.require(:default, :assets, Rails.env) +end + +module Elo + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + + # Enable the asset pipeline + config.assets.enabled = true + + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000..4489e58 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000..51a4dd4 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 + +production: + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000..45764b9 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Elo::Application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000..8e1af48 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,30 @@ +Elo::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Do not compress assets + config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000..749a223 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,60 @@ +Elo::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false + + # Compress JavaScripts and CSS + config.assets.compress = true + + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + + # Defaults to Rails.root.join("public/assets") + # config.assets.manifest = YOUR_PATH + + # Specifies the header that your server uses for sending files + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile += %w( search.js ) + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000..3aa4b50 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,39 @@ +Elo::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Configure static asset server for tests with Cache-Control for performance + config.serve_static_assets = true + config.static_cache_control = "public, max-age=3600" + + # Log error messages when you accidentally call methods on nil + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb new file mode 100644 index 0000000..8068e0c --- /dev/null +++ b/config/initializers/constants.rb @@ -0,0 +1,2 @@ +K_RATING_COEFFICIENT = 50 +F_RATING_INTERVAL_SCALE_WEIGHT = 1000 diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 0000000..9e8b013 --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,10 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb new file mode 100644 index 0000000..72aca7e --- /dev/null +++ b/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb new file mode 100644 index 0000000..bcc6cca --- /dev/null +++ b/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Elo::Application.config.secret_token = 'eb6535ecded353bf4022ee531cfd0cde7d6874b3cb57d15bb83966632496c00d143383b7294855accd14651cef615ae901fa85a44df2d19c736e2aaf023a5412' diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb new file mode 100644 index 0000000..369462a --- /dev/null +++ b/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Elo::Application.config.session_store :cookie_store, :key => '_elo_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Elo::Application.config.session_store :active_record_store diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..da4fb07 --- /dev/null +++ b/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters :format => [:json] +end + +# Disable root element in JSON by default. +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..179c14c --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..85bf084 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,62 @@ +Elo::Application.routes.draw do + resources :games + + resources :players + + # The priority is based upon order of creation: + # first created -> highest priority. + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => 'welcome#index' + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' +end diff --git a/db/migrate/20120119194929_create_players.rb b/db/migrate/20120119194929_create_players.rb new file mode 100644 index 0000000..9a5409b --- /dev/null +++ b/db/migrate/20120119194929_create_players.rb @@ -0,0 +1,11 @@ +class CreatePlayers < ActiveRecord::Migration + def change + create_table :players do |t| + t.string :email + t.integer :rank + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20120119195534_create_games.rb b/db/migrate/20120119195534_create_games.rb new file mode 100644 index 0000000..3a78568 --- /dev/null +++ b/db/migrate/20120119195534_create_games.rb @@ -0,0 +1,10 @@ +class CreateGames < ActiveRecord::Migration + def change + create_table :games do |t| + t.belongs_to :winner + t.belongs_to :loser + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..5878dd4 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,31 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20120119195534) do + + create_table "games", :force => true do |t| + t.integer "winner_id" + t.integer "loser_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "players", :force => true do |t| + t.string "email" + t.integer "rank" + t.string "name" + t.datetime "created_at" + t.datetime "updated_at" + end + +end diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000..d34dfa0 --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) +# Mayor.create(:name => 'Emanuel', :city => cities.first) diff --git a/doc/README_FOR_APP b/doc/README_FOR_APP new file mode 100644 index 0000000..fe41f5c --- /dev/null +++ b/doc/README_FOR_APP @@ -0,0 +1,2 @@ +Use this README file to introduce your application and point to useful places in the API for learning more. +Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/lib/assets/.gitkeep b/lib/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/lib/tasks/.gitkeep b/lib/tasks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/log/.gitkeep b/log/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..9a48320 --- /dev/null +++ b/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
    +

    The page you were looking for doesn't exist.

    +

    You may have mistyped the address or the page may have moved.

    +
    + + diff --git a/public/422.html b/public/422.html new file mode 100644 index 0000000..83660ab --- /dev/null +++ b/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
    +

    The change you wanted was rejected.

    +

    Maybe you tried to change something you didn't have access to.

    +
    + + diff --git a/public/500.html b/public/500.html new file mode 100644 index 0000000..b80307f --- /dev/null +++ b/public/500.html @@ -0,0 +1,26 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
    +

    We're sorry, but something went wrong.

    +

    We've been notified about this issue and we'll take a look at it shortly.

    +
    + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..9d9811a --- /dev/null +++ b/public/index.html @@ -0,0 +1,241 @@ + + + + Ruby on Rails: Welcome aboard + + + + +
    + + +
    + + + + +
    +

    Getting started

    +

    Here’s how to get rolling:

    + +
      +
    1. +

      Use rails generate to create your models and controllers

      +

      To see all available options, run it without parameters.

      +
    2. + +
    3. +

      Set up a default route and remove public/index.html

      +

      Routes are set up in config/routes.rb.

      +
    4. + +
    5. +

      Create your database

      +

      Run rake db:create to create your database. If you're not using SQLite (the default), edit config/database.yml with your username and password.

      +
    6. +
    +
    +
    + + +
    + + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..085187f --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / diff --git a/script/rails b/script/rails new file mode 100755 index 0000000..f8da2cf --- /dev/null +++ b/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/spec/controllers/games_controller_spec.rb b/spec/controllers/games_controller_spec.rb new file mode 100644 index 0000000..2a706ec --- /dev/null +++ b/spec/controllers/games_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe GamesController do + +end diff --git a/spec/controllers/players_controller_spec.rb b/spec/controllers/players_controller_spec.rb new file mode 100644 index 0000000..c7f54d5 --- /dev/null +++ b/spec/controllers/players_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe PlayersController do + +end diff --git a/spec/helpers/games_helper_spec.rb b/spec/helpers/games_helper_spec.rb new file mode 100644 index 0000000..72addeb --- /dev/null +++ b/spec/helpers/games_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the GamesHelper. For example: +# +# describe GamesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe GamesHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/players_helper_spec.rb b/spec/helpers/players_helper_spec.rb new file mode 100644 index 0000000..0902cab --- /dev/null +++ b/spec/helpers/players_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the PlayersHelper. For example: +# +# describe PlayersHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe PlayersHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb new file mode 100644 index 0000000..e451143 --- /dev/null +++ b/spec/models/game_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Game do + +end diff --git a/spec/models/player_spec.rb b/spec/models/player_spec.rb new file mode 100644 index 0000000..76981ed --- /dev/null +++ b/spec/models/player_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe Player do + context "requires email" do + Given(:player) { Player.new } + Then { player.should have(1).error_on(:email) } + end + + context "must have unique email" do + Given(:player) { Player.create!(:email => "bob@example.com") } + When(:dup) { Player.new(:email => player.email) } + Then { dup.should have(1).error_on(:email) } + end + + context "#new_rank" do + Given(:player) { Player.new(:rank => 1800) } + context "winning" do + Then { player.new_rank(1550, 1).should == 1818 } + end + + context "losing" do + Then { player.new_rank(1550, 0).should == 1768 } + end + end + + context "#win_expectancy" do + Given(:player) { Player.new } + Given(:data) { [[0, 50, 50],[25, 51, 49],[50, 53, 47],[75, 54, 46],[100, 56, 44],[150, 59, 41],[200, 61, 39],[250, 64, 36],[300, 67, 33],[350, 69, 31],[400, 72, 28],[450, 74, 26],[500, 76, 24],[600, 80, 20],[700, 83, 17],[800, 86, 14],[900, 89, 11],[1000, 91, 9],[1100, 93, 7],[1200, 94, 6],[1300, 95, 5],[1400, 96, 4],[1500, 97, 3],[1600, 98, 2],[1700, 98, 2],[1900, 99, 1],[2000, 99, 1],[2100, 99, 1],[2200, 99, 1 ]] } + Then do + data.each do |test| + player.win_expectancy(test[0]).should be_within(0.005).of(test[1].to_f/100) + end + end + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..e66d980 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,32 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +require 'rspec/autorun' + +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + +RSpec.configure do |config| + # ## Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + config.infer_base_class_for_anonymous_controllers = false +end diff --git a/vendor/assets/stylesheets/.gitkeep b/vendor/assets/stylesheets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/vendor/plugins/.gitkeep b/vendor/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/vendor/ruby/1.9.1/bin/autospec b/vendor/ruby/1.9.1/bin/autospec new file mode 100755 index 0000000..3c03255 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/autospec @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rspec-core' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rspec-core', version +load Gem.bin_path('rspec-core', 'autospec', version) diff --git a/vendor/ruby/1.9.1/bin/erubis b/vendor/ruby/1.9.1/bin/erubis new file mode 100755 index 0000000..9d8b1aa --- /dev/null +++ b/vendor/ruby/1.9.1/bin/erubis @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'erubis' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'erubis', version +load Gem.bin_path('erubis', 'erubis', version) diff --git a/vendor/ruby/1.9.1/bin/htmldiff b/vendor/ruby/1.9.1/bin/htmldiff new file mode 100755 index 0000000..222bb96 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/htmldiff @@ -0,0 +1,21 @@ +#!/bin/sh +'exec' "ruby" '-x' "$0" "$@" +#!/Users/dalcorn/.rbenv/versions/1.9.2-p290/bin/ruby -w +# +# This file was generated by RubyGems. +# +# The application 'diff-lcs' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'diff-lcs', version +load Gem.bin_path('diff-lcs', 'htmldiff', version) diff --git a/vendor/ruby/1.9.1/bin/ldiff b/vendor/ruby/1.9.1/bin/ldiff new file mode 100755 index 0000000..8255850 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/ldiff @@ -0,0 +1,21 @@ +#!/bin/sh +'exec' "ruby" '-x' "$0" "$@" +#!/Users/dalcorn/.rbenv/versions/1.9.2-p290/bin/ruby -w +# +# This file was generated by RubyGems. +# +# The application 'diff-lcs' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'diff-lcs', version +load Gem.bin_path('diff-lcs', 'ldiff', version) diff --git a/vendor/ruby/1.9.1/bin/rackup b/vendor/ruby/1.9.1/bin/rackup new file mode 100755 index 0000000..a1b1b80 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/rackup @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rack' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rack', version +load Gem.bin_path('rack', 'rackup', version) diff --git a/vendor/ruby/1.9.1/bin/rails b/vendor/ruby/1.9.1/bin/rails new file mode 100755 index 0000000..a5dba75 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/rails @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rails' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rails', version +load Gem.bin_path('rails', 'rails', version) diff --git a/vendor/ruby/1.9.1/bin/rake b/vendor/ruby/1.9.1/bin/rake new file mode 100755 index 0000000..3cdbde2 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/rake @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rake', version +load Gem.bin_path('rake', 'rake', version) diff --git a/vendor/ruby/1.9.1/bin/rake2thor b/vendor/ruby/1.9.1/bin/rake2thor new file mode 100755 index 0000000..daa4cc9 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/rake2thor @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'thor', version +load Gem.bin_path('thor', 'rake2thor', version) diff --git a/vendor/ruby/1.9.1/bin/rdoc b/vendor/ruby/1.9.1/bin/rdoc new file mode 100755 index 0000000..631ebc8 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/rdoc @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rdoc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rdoc', version +load Gem.bin_path('rdoc', 'rdoc', version) diff --git a/vendor/ruby/1.9.1/bin/ri b/vendor/ruby/1.9.1/bin/ri new file mode 100755 index 0000000..9287d90 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/ri @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rdoc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rdoc', version +load Gem.bin_path('rdoc', 'ri', version) diff --git a/vendor/ruby/1.9.1/bin/rspec b/vendor/ruby/1.9.1/bin/rspec new file mode 100755 index 0000000..9dfce78 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/rspec @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'rspec-core' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rspec-core', version +load Gem.bin_path('rspec-core', 'rspec', version) diff --git a/vendor/ruby/1.9.1/bin/sass b/vendor/ruby/1.9.1/bin/sass new file mode 100755 index 0000000..bed6f53 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/sass @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'sass' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'sass', version +load Gem.bin_path('sass', 'sass', version) diff --git a/vendor/ruby/1.9.1/bin/sass-convert b/vendor/ruby/1.9.1/bin/sass-convert new file mode 100755 index 0000000..63f449f --- /dev/null +++ b/vendor/ruby/1.9.1/bin/sass-convert @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'sass' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'sass', version +load Gem.bin_path('sass', 'sass-convert', version) diff --git a/vendor/ruby/1.9.1/bin/scss b/vendor/ruby/1.9.1/bin/scss new file mode 100755 index 0000000..3da6a26 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/scss @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'sass' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'sass', version +load Gem.bin_path('sass', 'scss', version) diff --git a/vendor/ruby/1.9.1/bin/thor b/vendor/ruby/1.9.1/bin/thor new file mode 100755 index 0000000..2f2d5b5 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/thor @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'thor', version +load Gem.bin_path('thor', 'thor', version) diff --git a/vendor/ruby/1.9.1/bin/tilt b/vendor/ruby/1.9.1/bin/tilt new file mode 100755 index 0000000..7375e1f --- /dev/null +++ b/vendor/ruby/1.9.1/bin/tilt @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'tilt' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'tilt', version +load Gem.bin_path('tilt', 'tilt', version) diff --git a/vendor/ruby/1.9.1/bin/tt b/vendor/ruby/1.9.1/bin/tt new file mode 100755 index 0000000..e24f7b2 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/tt @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'treetop' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'treetop', version +load Gem.bin_path('treetop', 'tt', version) diff --git a/vendor/ruby/1.9.1/cache/actionmailer-3.1.1.gem b/vendor/ruby/1.9.1/cache/actionmailer-3.1.1.gem new file mode 100644 index 0000000..5277566 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/actionmailer-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/actionpack-3.1.1.gem b/vendor/ruby/1.9.1/cache/actionpack-3.1.1.gem new file mode 100644 index 0000000..73ebe35 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/actionpack-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/activemodel-3.1.1.gem b/vendor/ruby/1.9.1/cache/activemodel-3.1.1.gem new file mode 100644 index 0000000..be5acf7 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/activemodel-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/activerecord-3.1.1.gem b/vendor/ruby/1.9.1/cache/activerecord-3.1.1.gem new file mode 100644 index 0000000..e871499 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/activerecord-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/activeresource-3.1.1.gem b/vendor/ruby/1.9.1/cache/activeresource-3.1.1.gem new file mode 100644 index 0000000..f5ebf4c Binary files /dev/null and b/vendor/ruby/1.9.1/cache/activeresource-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/activesupport-3.1.1.gem b/vendor/ruby/1.9.1/cache/activesupport-3.1.1.gem new file mode 100644 index 0000000..516757d Binary files /dev/null and b/vendor/ruby/1.9.1/cache/activesupport-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/arel-2.2.1.gem b/vendor/ruby/1.9.1/cache/arel-2.2.1.gem new file mode 100644 index 0000000..4764f54 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/arel-2.2.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/builder-3.0.0.gem b/vendor/ruby/1.9.1/cache/builder-3.0.0.gem new file mode 100644 index 0000000..a2c6d16 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/builder-3.0.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/coffee-rails-3.1.1.gem b/vendor/ruby/1.9.1/cache/coffee-rails-3.1.1.gem new file mode 100644 index 0000000..ec4daab Binary files /dev/null and b/vendor/ruby/1.9.1/cache/coffee-rails-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/coffee-script-2.2.0.gem b/vendor/ruby/1.9.1/cache/coffee-script-2.2.0.gem new file mode 100644 index 0000000..c33f4d9 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/coffee-script-2.2.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/coffee-script-source-1.2.0.gem b/vendor/ruby/1.9.1/cache/coffee-script-source-1.2.0.gem new file mode 100644 index 0000000..99fbd48 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/coffee-script-source-1.2.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/diff-lcs-1.1.3.gem b/vendor/ruby/1.9.1/cache/diff-lcs-1.1.3.gem new file mode 100644 index 0000000..8767f39 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/diff-lcs-1.1.3.gem differ diff --git a/vendor/ruby/1.9.1/cache/erubis-2.7.0.gem b/vendor/ruby/1.9.1/cache/erubis-2.7.0.gem new file mode 100644 index 0000000..4acd2e7 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/erubis-2.7.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/execjs-1.3.0.gem b/vendor/ruby/1.9.1/cache/execjs-1.3.0.gem new file mode 100644 index 0000000..d1275b1 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/execjs-1.3.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/has_scope-0.5.1.gem b/vendor/ruby/1.9.1/cache/has_scope-0.5.1.gem new file mode 100644 index 0000000..c4a7e27 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/has_scope-0.5.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/hike-1.2.1.gem b/vendor/ruby/1.9.1/cache/hike-1.2.1.gem new file mode 100644 index 0000000..9bf7631 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/hike-1.2.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/i18n-0.6.0.gem b/vendor/ruby/1.9.1/cache/i18n-0.6.0.gem new file mode 100644 index 0000000..1ad8176 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/i18n-0.6.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/inherited_resources-1.3.0.gem b/vendor/ruby/1.9.1/cache/inherited_resources-1.3.0.gem new file mode 100644 index 0000000..ad8bcc3 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/inherited_resources-1.3.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/jquery-rails-1.0.19.gem b/vendor/ruby/1.9.1/cache/jquery-rails-1.0.19.gem new file mode 100644 index 0000000..6bace21 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/jquery-rails-1.0.19.gem differ diff --git a/vendor/ruby/1.9.1/cache/json-1.6.5.gem b/vendor/ruby/1.9.1/cache/json-1.6.5.gem new file mode 100644 index 0000000..ac0f155 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/json-1.6.5.gem differ diff --git a/vendor/ruby/1.9.1/cache/mail-2.3.0.gem b/vendor/ruby/1.9.1/cache/mail-2.3.0.gem new file mode 100644 index 0000000..f1dcdbe Binary files /dev/null and b/vendor/ruby/1.9.1/cache/mail-2.3.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/mime-types-1.17.2.gem b/vendor/ruby/1.9.1/cache/mime-types-1.17.2.gem new file mode 100644 index 0000000..fbb5011 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/mime-types-1.17.2.gem differ diff --git a/vendor/ruby/1.9.1/cache/multi_json-1.0.4.gem b/vendor/ruby/1.9.1/cache/multi_json-1.0.4.gem new file mode 100644 index 0000000..2c86240 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/multi_json-1.0.4.gem differ diff --git a/vendor/ruby/1.9.1/cache/polyglot-0.3.3.gem b/vendor/ruby/1.9.1/cache/polyglot-0.3.3.gem new file mode 100644 index 0000000..0b87664 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/polyglot-0.3.3.gem differ diff --git a/vendor/ruby/1.9.1/cache/rack-1.3.6.gem b/vendor/ruby/1.9.1/cache/rack-1.3.6.gem new file mode 100644 index 0000000..5d7cddf Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rack-1.3.6.gem differ diff --git a/vendor/ruby/1.9.1/cache/rack-cache-1.1.gem b/vendor/ruby/1.9.1/cache/rack-cache-1.1.gem new file mode 100644 index 0000000..41bbf5d Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rack-cache-1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/rack-mount-0.8.3.gem b/vendor/ruby/1.9.1/cache/rack-mount-0.8.3.gem new file mode 100644 index 0000000..a88d4f2 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rack-mount-0.8.3.gem differ diff --git a/vendor/ruby/1.9.1/cache/rack-ssl-1.3.2.gem b/vendor/ruby/1.9.1/cache/rack-ssl-1.3.2.gem new file mode 100644 index 0000000..098fa4a Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rack-ssl-1.3.2.gem differ diff --git a/vendor/ruby/1.9.1/cache/rack-test-0.6.1.gem b/vendor/ruby/1.9.1/cache/rack-test-0.6.1.gem new file mode 100644 index 0000000..ec51bba Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rack-test-0.6.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/rails-3.1.1.gem b/vendor/ruby/1.9.1/cache/rails-3.1.1.gem new file mode 100644 index 0000000..3b6e7d3 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rails-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/railties-3.1.1.gem b/vendor/ruby/1.9.1/cache/railties-3.1.1.gem new file mode 100644 index 0000000..07db598 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/railties-3.1.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/rake-0.9.2.2.gem b/vendor/ruby/1.9.1/cache/rake-0.9.2.2.gem new file mode 100644 index 0000000..f7239ac Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rake-0.9.2.2.gem differ diff --git a/vendor/ruby/1.9.1/cache/rdoc-3.12.gem b/vendor/ruby/1.9.1/cache/rdoc-3.12.gem new file mode 100644 index 0000000..0c21498 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rdoc-3.12.gem differ diff --git a/vendor/ruby/1.9.1/cache/resource_controller-0.6.6.gem b/vendor/ruby/1.9.1/cache/resource_controller-0.6.6.gem new file mode 100644 index 0000000..22949da Binary files /dev/null and b/vendor/ruby/1.9.1/cache/resource_controller-0.6.6.gem differ diff --git a/vendor/ruby/1.9.1/cache/responders-0.6.4.gem b/vendor/ruby/1.9.1/cache/responders-0.6.4.gem new file mode 100644 index 0000000..af5a463 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/responders-0.6.4.gem differ diff --git a/vendor/ruby/1.9.1/cache/rspec-2.8.0.gem b/vendor/ruby/1.9.1/cache/rspec-2.8.0.gem new file mode 100644 index 0000000..16caed4 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rspec-2.8.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/rspec-core-2.8.0.gem b/vendor/ruby/1.9.1/cache/rspec-core-2.8.0.gem new file mode 100644 index 0000000..6c8e7b5 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rspec-core-2.8.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/rspec-expectations-2.8.0.gem b/vendor/ruby/1.9.1/cache/rspec-expectations-2.8.0.gem new file mode 100644 index 0000000..abfdf94 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rspec-expectations-2.8.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/rspec-given-1.4.2.gem b/vendor/ruby/1.9.1/cache/rspec-given-1.4.2.gem new file mode 100644 index 0000000..c7687ce Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rspec-given-1.4.2.gem differ diff --git a/vendor/ruby/1.9.1/cache/rspec-mocks-2.8.0.gem b/vendor/ruby/1.9.1/cache/rspec-mocks-2.8.0.gem new file mode 100644 index 0000000..3d33d74 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rspec-mocks-2.8.0.gem differ diff --git a/vendor/ruby/1.9.1/cache/rspec-rails-2.8.1.gem b/vendor/ruby/1.9.1/cache/rspec-rails-2.8.1.gem new file mode 100644 index 0000000..ca93293 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/rspec-rails-2.8.1.gem differ diff --git a/vendor/ruby/1.9.1/cache/sass-3.1.12.gem b/vendor/ruby/1.9.1/cache/sass-3.1.12.gem new file mode 100644 index 0000000..7bcb72d Binary files /dev/null and b/vendor/ruby/1.9.1/cache/sass-3.1.12.gem differ diff --git a/vendor/ruby/1.9.1/cache/sass-rails-3.1.5.gem b/vendor/ruby/1.9.1/cache/sass-rails-3.1.5.gem new file mode 100644 index 0000000..73859c5 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/sass-rails-3.1.5.gem differ diff --git a/vendor/ruby/1.9.1/cache/simple_form-1.5.2.gem b/vendor/ruby/1.9.1/cache/simple_form-1.5.2.gem new file mode 100644 index 0000000..c882a03 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/simple_form-1.5.2.gem differ diff --git a/vendor/ruby/1.9.1/cache/sprockets-2.0.3.gem b/vendor/ruby/1.9.1/cache/sprockets-2.0.3.gem new file mode 100644 index 0000000..a90a8f1 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/sprockets-2.0.3.gem differ diff --git a/vendor/ruby/1.9.1/cache/sqlite3-1.3.5.gem b/vendor/ruby/1.9.1/cache/sqlite3-1.3.5.gem new file mode 100644 index 0000000..a251640 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/sqlite3-1.3.5.gem differ diff --git a/vendor/ruby/1.9.1/cache/thor-0.14.6.gem b/vendor/ruby/1.9.1/cache/thor-0.14.6.gem new file mode 100644 index 0000000..ce40e0c Binary files /dev/null and b/vendor/ruby/1.9.1/cache/thor-0.14.6.gem differ diff --git a/vendor/ruby/1.9.1/cache/tilt-1.3.3.gem b/vendor/ruby/1.9.1/cache/tilt-1.3.3.gem new file mode 100644 index 0000000..2754964 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/tilt-1.3.3.gem differ diff --git a/vendor/ruby/1.9.1/cache/treetop-1.4.10.gem b/vendor/ruby/1.9.1/cache/treetop-1.4.10.gem new file mode 100644 index 0000000..3c98f3d Binary files /dev/null and b/vendor/ruby/1.9.1/cache/treetop-1.4.10.gem differ diff --git a/vendor/ruby/1.9.1/cache/tzinfo-0.3.31.gem b/vendor/ruby/1.9.1/cache/tzinfo-0.3.31.gem new file mode 100644 index 0000000..7a7d571 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/tzinfo-0.3.31.gem differ diff --git a/vendor/ruby/1.9.1/cache/uglifier-1.2.2.gem b/vendor/ruby/1.9.1/cache/uglifier-1.2.2.gem new file mode 100644 index 0000000..23047b1 Binary files /dev/null and b/vendor/ruby/1.9.1/cache/uglifier-1.2.2.gem differ diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/CHANGELOG b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/CHANGELOG new file mode 100644 index 0000000..defe5a7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/CHANGELOG @@ -0,0 +1,454 @@ +*Rails 3.1.1 (unreleased)* + +* No changes + + +*Rails 3.1.0 (August 30, 2011)* + +* No changes + + +*Rails 3.0.7 (April 18, 2011)* + +* remove AM delegating register_observer and register_interceptor to Mail [Josh Kalderimis] + + +*Rails 3.0.6 (April 5, 2011) + +* Don't allow i18n to change the minor version, version now set to ~> 0.5.0 [Santiago Pastorino] + + +*Rails 3.0.5 (February 26, 2011)* + +* No changes. + + +*Rails 3.0.4 (February 8, 2011)* + +* No changes. + + +*Rails 3.0.3 (November 16, 2010)* + +* No changes. + + +*Rails 3.0.2 (November 15, 2010)* + +* No changes + + +*Rails 3.0.1 (October 15, 2010)* + +* No Changes, just a version bump. + + +*Rails 3.0.0 (August 29, 2010)* + +* subject is automatically looked up on I18n using mailer_name and action_name as scope as in t(".subject") [JK] + +* Changed encoding behaviour of mail, so updated tests in actionmailer and bumped mail version to 2.2.1 [ML] + +* Added ability to pass Proc objects to the defaults hash [ML] + +* Removed all quoting.rb type files from ActionMailer and put Mail 2.2.0 in instead [ML] + +* Lot of updates to various test cases that now work better with the new Mail and so have different expectations + +* Added interceptors and observers from Mail [ML] + + ActionMailer::Base.register_interceptor calls Mail.register_interceptor + ActionMailer::Base.register_observer calls Mail.register_observer + +* Mail::Part now no longer has nil as a default charset, it is always set to something, and defaults to UTF-8 + +* Added explict setting of charset in set_fields! method to make sure Mail has the user defined default + +* Removed quoting.rb and refactored for Mail to take responsibility of all quoting and auto encoding requirements for the header. + +* Fixed several tests which had incorrect encoding. + +* Changed all utf-8 to UTF-8 for consistency + +* Whole new API added with tests. See base.rb for full details. Old API is deprecated. + +* The Mail::Message class has helped methods for all the field types that return 'common' defaults for the common use case, so to get the subject, mail.subject will give you a string, mail.date will give you a DateTime object, mail.from will give you an array of address specs (mikel@test.lindsaar.net) etc. If you want to access the field object itself, call mail[:field_name] which will return the field object you want, which you can then chain, like mail[:from].formatted + +* Mail#content_type now returns the content_type field as a string. If you want the mime type of a mail, then you call Mail#mime_type (eg, text/plain), if you want the parameters of the content type field, you call Mail#content_type_parameters which gives you a hash, eg {'format' => 'flowed', 'charset' => 'utf-8'} + +* ActionMailer::Base :default_implicit_parts_order now is in the sequence of the order you want, no reversing of ordering takes place. The default order now is text/plain, then text/enriched, then text/html and then any other part that is not one of these three. + +* Mail does not have "quoted_body", "quoted_subject" etc. All of these are accessed via body.encoded, subject.encoded etc + +* Every object in a Mail object returns an object, never a string. So Mail.body returns a Mail::Body class object, need to call #encoded or #decoded to get the string you want. +* Mail::Message#set_content_type does not exist, it is simply Mail::Message#content_type + +* Every mail message gets a unique message_id unless you specify one, had to change all the tests that check for equality with expected.encoded == actual.encoded to first replace their message_ids with control values + +* Mail now has a proper concept of parts, remove the ActionMailer::Part and ActionMailer::PartContainer classes + +* Calling #encoded on any object returns it as a string ready to go into the output stream of an email, this means it includes the \r\n at the end of the lines and the object is pre-wrapped with \r\n\t if it is a header field. Also, the "encoded" value includes the field name if it is a header field. + +* Attachments are only the actual attachment, with filename etc. A part contains an attachment. The part has the content_type etc. So attachments.last.content_type is invalid. But parts.last.content_type + +* There is no idea of a "sub_head" in Mail. A part is just a Message with some extra functionality, so it just has a "header" like a normal mail message + + +*2.3.2 [Final] (March 15, 2009)* + +* Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones] + +* Fixed RFC-2045 quoted-printable bug #1421 [squadette] + +* Fixed that no body charset would be set when there are attachments present #740 [Paweł Kondzior] + + +*2.2.1 [RC2] (November 14th, 2008)* + +* Turn on STARTTLS if it is available in Net::SMTP (added in Ruby 1.8.7) and the SMTP server supports it (This is required for Gmail's SMTP server) #1336 [Grant Hollingworth] + + +*2.2.0 [RC1] (October 24th, 2008)* + +* Add layout functionality to mailers [Pratik Naik] + + Mailer layouts behaves just like controller layouts, except layout names need to + have '_mailer' postfix for them to be automatically picked up. + + +*2.1.0 (May 31st, 2008)* + +* Fixed that a return-path header would be ignored #7572 [joost] + +* Less verbose mail logging: just recipients for :info log level; the whole email for :debug only. #8000 [iaddict, Tarmo Tänav] + +* Updated TMail to version 1.2.1 [Mikel Lindsaar] + +* Fixed that you don't have to call super in ActionMailer::TestCase#setup #10406 [jamesgolick] + + +*2.0.2* (December 16th, 2007) + +* Included in Rails 2.0.2 + + +*2.0.1* (December 7th, 2007) + +* Update ActionMailer so it treats ActionView the same way that ActionController does. Closes #10244 [Rick Olson] + + * Pass the template_root as an array as ActionView's view_path + * Request templates with the "#{mailer_name}/#{action}" as opposed to just "#{action}" + +* Fixed that partials would be broken when using text.plain.erb as the extension #10130 [java] + +* Update README to use new smtp settings configuration API. Closes #10060 [psq] + +* Allow ActionMailer subclasses to individually set their delivery method (so two subclasses can have different delivery methods) #10033 [Zach Dennis] + +* Update TMail to v1.1.0. Use an updated version of TMail if available. [Mikel Lindsaar] + +* Introduce a new base test class for testing Mailers. ActionMailer::TestCase [Michael Koziarski] + +* Fix silent failure of rxml templates. #9879 [jstewart] + +* Fix attachment decoding when using the TMail C extension. #7861 [orangechicken] + +* Increase mail delivery test coverage. #8692 [Kamal Fariz Mahyuddin] + +* Register alternative template engines using ActionMailer::Base.register_template_extension('haml'). #7534 [cwd, Josh Peek] + +* Only load ActionController::UrlWriter if ActionController is present [Rick Olson] + +* Make sure parsed emails recognized attachments nested inside multipart parts. #6714 [Jamis Buck] + +* Allow mailer actions named send by using __send__ internally. #6467 [iGEL] + +* Add assert_emails and assert_no_emails to test the number of emails delivered. #6479 [Jonathan Viney] + # Assert total number of emails delivered: + assert_emails 0 + ContactMailer.deliver_contact + assert_emails 1 + + # Assert number of emails delivered within a block: + assert_emails 1 do + post :signup, :name => 'Jonathan' + end + + +*1.3.3* (March 12th, 2007) + +* Depend on Action Pack 1.13.3 + + +*1.3.2* (February 5th, 2007) + +* Deprecate server_settings renaming it to smtp_settings, add sendmail_settings to allow you to override the arguments to and location of the sendmail executable. [Michael Koziarski] + + +*1.3.1* (January 16th, 2007) + +* Depend on Action Pack 1.13.1 + + +*1.3.0* (January 16th, 2007) + +* Make mime version default to 1.0. closes #2323 [ror@andreas-s.net] + +* Make sure quoted-printable text is decoded correctly when only portions of the text are encoded. closes #3154. [jon@siliconcircus.com] + +* Make sure DOS newlines in quoted-printable text are normalized to unix newlines before unquoting. closes #4166 and #4452. [Jamis Buck] + +* Fixed that iconv decoding should catch InvalidEncoding #3153 [jon@siliconcircus.com] + +* Tighten rescue clauses. #5985 [james@grayproductions.net] + +* Automatically included ActionController::UrlWriter, such that URL generation can happen within ActionMailer controllers. [David Heinemeier Hansson] + +* Replace Reloadable with Reloadable::Deprecated. [Nicholas Seckar] + +* Mailer template root applies to a class and its subclasses rather than acting globally. #5555 [somekool@gmail.com] + +* Resolve action naming collision. #5520 [ssinghi@kreeti.com] + +* ActionMailer::Base documentation rewrite. Closes #4991 [Kevin Clark, Marcel Molina Jr.] + +* Replace alias method chaining with Module#alias_method_chain. [Marcel Molina Jr.] + +* Replace Ruby's deprecated append_features in favor of included. [Marcel Molina Jr.] + +* Correct spurious documentation example code which results in a SyntaxError. [Marcel Molina Jr.] + + +*1.2.1* (April 6th, 2006) + +* Be part of Rails 1.1.1 + + +*1.2.0* (March 27th, 2006) + +* Nil charset caused subject line to be improperly quoted in implicitly multipart messages #2662 [ehalvorsen+rails@runbox.com] + +* Parse content-type apart before using it so that sub-parts of the header can be set correctly #2918 [Jamis Buck] + +* Make custom headers work in subparts #4034 [elan@bluemandrill.com] + +* Template paths with dot chars in them no longer mess up implicit template selection for multipart messages #3332 [Chad Fowler] + +* Make sure anything with content-disposition of "attachment" is passed to the attachment presenter when parsing an email body [Jamis Buck] + +* Make sure TMail#attachments includes anything with content-disposition of "attachment", regardless of content-type [Jamis Buck] + + +*1.1.5* (December 13th, 2005) + +* Become part of Rails 1.0 + + +*1.1.4* (December 7th, 2005) + +* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] + +* Stricter matching for implicitly multipart filenames excludes files ending in unsupported extensions (such as foo.rhtml.bak) and without a two-part content type (such as foo.text.rhtml or foo.text.really.plain.rhtml). #2398 [Dave Burt , Jeremy Kemper] + + +*1.1.3* (November 7th, 2005) + +* Allow Mailers to have custom initialize methods that set default instance variables for all mail actions #2563 [mrj@bigpond.net.au] + + +*1.1.2* (October 26th, 2005) + +* Upgraded to Action Pack 1.10.2 + + +*1.1.1* (October 19th, 2005) + +* Upgraded to Action Pack 1.10.1 + + +*1.1.0* (October 16th, 2005) + +* Update and extend documentation (rdoc) + +* Minero Aoki made TMail available to Rails/ActionMailer under the MIT license (instead of LGPL) [RubyConf '05] + +* Austin Ziegler made Text::Simple available to Rails/ActionMailer under a MIT-like licens [See rails ML, subject "Text::Format Licence Exception" on Oct 15, 2005] + +* Fix vendor require paths to prevent files being required twice + +* Don't add charset to content-type header for a part that contains subparts (for AOL compatibility) #2013 [John Long] + +* Preserve underscores when unquoting message bodies #1930 + +* Encode multibyte characters correctly #1894 + +* Multipart messages specify a MIME-Version header automatically #2003 [John Long] + +* Add a unified render method to ActionMailer (delegates to ActionView::Base#render) + +* Move mailer initialization to a separate (overridable) method, so that subclasses may alter the various defaults #1727 + +* Look at content-location header (if available) to determine filename of attachments #1670 + +* ActionMailer::Base.deliver(email) had been accidentally removed, but was documented in the Rails book #1849 + +* Fix problem with sendmail delivery where headers should be delimited by \n characters instead of \r\n, which confuses some mail readers #1742 [Kent Sibilev] + + +*1.0.1* (11 July, 2005) + +* Bind to Action Pack 1.9.1 + + +*1.0.0* (6 July, 2005) + +* Avoid adding nil header values #1392 + +* Better multipart support with implicit multipart/alternative and sorting of subparts [John Long] + +* Allow for nested parts in multipart mails #1570 [Flurin Egger] + +* Normalize line endings in outgoing mail bodies to "\n" #1536 [John Long] + +* Allow template to be explicitly specified #1448 [tuxie@dekadance.se] + +* Allow specific "multipart/xxx" content-type to be set on multipart messages #1412 [Flurin Egger] + +* Unquoted @ characters in headers are now accepted in spite of RFC 822 #1206 + +* Helper support (borrowed from ActionPack) + +* Silently ignore Errno::EINVAL errors when converting text. + +* Don't cause an error when parsing an encoded attachment name #1340 [lon@speedymac.com] + +* Nested multipart message parts are correctly processed in TMail::Mail#body + +* BCC headers are removed when sending via SMTP #1402 + +* Added 'content_type' accessor, to allow content type to be set on a per-message basis. content_type defaults to "text/plain". + +* Silently ignore Iconv::IllegalSequence errors when converting text #1341 [lon@speedymac.com] + +* Support attachments and multipart messages. + +* Added new accessors for the various mail properties. + +* Fix to only perform the charset conversion if a 'from' and a 'to' charset are given (make no assumptions about what the charset was) #1276 [Jamis Buck] + +* Fix attachments and content-type problems #1276 [Jamis Buck] + +* Fixed the TMail#body method to look at the content-transfer-encoding header and unquote the body according to the rules it specifies #1265 [Jamis Buck] + +* Added unquoting even if the iconv lib can't be loaded--in that case, only the charset conversion is skipped #1265 [Jamis Buck] + +* Added automatic decoding of base64 bodies #1214 [Jamis Buck] + +* Added that delivery errors are caught in a way so the mail is still returned whether the delivery was successful or not + +* Fixed that email address like "Jamis Buck, M.D." would cause the quoter to generate emails resulting in "bad address" errors from the mail server #1220 [Jamis Buck] + + +*0.9.1* (20th April, 2005) + +* Depend on Action Pack 1.8.1 + + +*0.9.0* (19th April, 2005) + +* Added that deliver_* will now return the email that was sent + +* Added that quoting to UTF-8 only happens if the characters used are in that range #955 [Jamis Buck] + +* Fixed quoting for all address headers, not just to #955 [Jamis Buck] + +* Fixed unquoting of emails that doesn't have an explicit charset #1036 [wolfgang@stufenlos.net] + + +*0.8.1* (27th March, 2005) + +* Fixed that if charset was found that the end of a mime part declaration TMail would throw an error #919 [lon@speedymac.com] + +* Fixed that TMail::Unquoter would fail to recognize quoting method if it was in lowercase #919 [lon@speedymac.com] + +* Fixed that TMail::Encoder would fail when it attempts to parse e-mail addresses which are encoded using something other than the messages encoding method #919 [lon@speedymac.com] + +* Added rescue for missing iconv library and throws warnings if subject/body is called on a TMail object without it instead + + +*0.8.0* (22th March, 2005) + +* Added framework support for processing incoming emails with an Action Mailer class. See example in README. + + +*0.7.1* (7th March, 2005) + +* Bind to newest Action Pack (1.5.1) + + +*0.7.0* (24th February, 2005) + +* Added support for charsets for both subject and body. The default charset is now UTF-8 #673 [Jamis Buck]. Examples: + + def iso_charset(recipient) + @recipients = recipient + @subject = "testing iso charsets" + @from = "system@loudthinking.com" + @body = "Nothing to see here." + @charset = "iso-8859-1" + end + + def unencoded_subject(recipient) + @recipients = recipient + @subject = "testing unencoded subject" + @from = "system@loudthinking.com" + @body = "Nothing to see here." + @encode_subject = false + @charset = "iso-8859-1" + end + + +*0.6.1* (January 18th, 2005) + +* Fixed sending of emails to use Tmail#from not the deprecated Tmail#from_address + + +*0.6* (January 17th, 2005) + +* Fixed that bcc and cc should be settable through @bcc and @cc -- not just @headers["Bcc"] and @headers["Cc"] #453 [Eric Hodel] + +* Fixed Action Mailer to be "warnings safe" so you can run with ruby -w and not get framework warnings #453 [Eric Hodel] + + +*0.5* + +* Added access to custom headers, like cc, bcc, and reply-to #268 [Andreas Schwarz]. Example: + + def post_notification(recipients, post) + @recipients = recipients + @from = post.author.email_address_with_name + @headers["bcc"] = SYSTEM_ADMINISTRATOR_EMAIL + @headers["reply-to"] = "notifications@example.com" + @subject = "[#{post.account.name} #{post.title}]" + @body["post"] = post + end + +*0.4* (5) + +* Consolidated the server configuration options into Base#server_settings= and expanded that with controls for authentication and more [Marten] + NOTE: This is an API change that could potentially break your application if you used the old application form. Please do change! + +* Added Base#deliveries as an accessor for an array of emails sent out through that ActionMailer class when using the :test delivery option. [Jeremy Kemper] + +* Added Base#perform_deliveries= which can be set to false to turn off the actual delivery of the email through smtp or sendmail. + This is especially useful for functional testing that shouldn't send off real emails, but still trigger delivery_* methods. + +* Added option to specify delivery method with Base#delivery_method=. Default is :smtp and :sendmail is currently the only other option. + Sendmail is assumed to be present at "/usr/sbin/sendmail" if that option is used. [Kent Sibilev] + +* Dropped "include TMail" as it added to much baggage into the default namespace (like Version) [Chad Fowler] + + +*0.3* + +* First release diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/MIT-LICENSE b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/MIT-LICENSE new file mode 100644 index 0000000..7ad1051 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/MIT-LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2004-2011 David Heinemeier Hansson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/README.rdoc b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/README.rdoc new file mode 100644 index 0000000..ab3a1c8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/README.rdoc @@ -0,0 +1,163 @@ += Action Mailer -- Easy email delivery and testing + +Action Mailer is a framework for designing email-service layers. These layers +are used to consolidate code for sending out forgotten passwords, welcome +wishes on signup, invoices for billing, and any other use case that requires +a written notification to either a person or another system. + +Action Mailer is in essence a wrapper around Action Controller and the +Mail gem. It provides a way to make emails using templates in the same +way that Action Controller renders views using templates. + +Additionally, an Action Mailer class can be used to process incoming email, +such as allowing a blog to accept new posts from an email (which could even +have been sent from a phone). + +== Sending emails + +The framework works by initializing any instance variables you want to be +available in the email template, followed by a call to +mail+ to deliver +the email. + +This can be as simple as: + + class Notifier < ActionMailer::Base + delivers_from 'system@loudthinking.com' + + def welcome(recipient) + @recipient = recipient + mail(:to => recipient, + :subject => "[Signed up] Welcome #{recipient}") + end + end + +The body of the email is created by using an Action View template (regular +ERB) that has the instance variables that are declared in the mailer action. + +So the corresponding body template for the method above could look like this: + + Hello there, + + Mr. <%= @recipient %> + + Thank you for signing up! + +And if the recipient was given as "david@loudthinking.com", the email +generated would look like this: + + Date: Mon, 25 Jan 2010 22:48:09 +1100 + From: system@loudthinking.com + To: david@loudthinking.com + Message-ID: <4b5d84f9dd6a5_7380800b81ac29578@void.loudthinking.com.mail> + Subject: [Signed up] Welcome david@loudthinking.com + Mime-Version: 1.0 + Content-Type: text/plain; + charset="US-ASCII"; + Content-Transfer-Encoding: 7bit + + Hello there, + + Mr. david@loudthinking.com + + Thank you for signing up! + +In previous version of Rails you would call create_method_name and +deliver_method_name. Rails 3.0 has a much simpler interface, you +simply call the method and optionally call +deliver+ on the return value. + +Calling the method returns a Mail Message object: + + message = Notifier.welcome # => Returns a Mail::Message object + message.deliver # => delivers the email + +Or you can just chain the methods together like: + + Notifier.welcome.deliver # Creates the email and sends it immediately + +== Setting defaults + +It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method default which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers e-mail messages has, like :from as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally it is also possible to pass in a Proc that will get evaluated when it is needed. + +Note that every value you set with this method will get over written if you use the same key in your mailer method. + +Example: + + class Authenticationmailer < ActionMailer::Base + default :from => "awesome@application.com", :subject => Proc.new { "E-mail was generated at #{Time.now}" } + ..... + end + +== Receiving emails + +To receive emails, you need to implement a public instance method called receive that takes an +email object as its single parameter. The Action Mailer framework has a corresponding class method, +which is also called receive, that accepts a raw, unprocessed email as a string, which it then turns +into the email object and calls the receive instance method. + +Example: + + class Mailman < ActionMailer::Base + def receive(email) + page = Page.find_by_address(email.to.first) + page.emails.create( + :subject => email.subject, :body => email.body + ) + + if email.has_attachments? + email.attachments.each do |attachment| + page.attachments.create({ + :file => attachment, :description => email.subject + }) + end + end + end + end + +This Mailman can be the target for Postfix or other MTAs. In Rails, you would use the runner in the +trivial case like this: + + rails runner 'Mailman.receive(STDIN.read)' + +However, invoking Rails in the runner for each mail to be received is very resource intensive. A single +instance of Rails should be run within a daemon, if it is going to be utilized to process more than just +a limited number of email. + +== Configuration + +The Base class has the full list of configuration options. Here's an example: + + ActionMailer::Base.smtp_settings = { + :address => 'smtp.yourserver.com', # default: localhost + :port => '25', # default: 25 + :user_name => 'user', + :password => 'pass', + :authentication => :plain # :plain, :login or :cram_md5 + } + + +== Download and installation + +The latest version of Action Mailer can be installed with Rubygems: + + % [sudo] gem install actionmailer + +Source code can be downloaded as part of the Rails project on GitHub + +* https://github.com/rails/rails/tree/master/actionmailer + + +== License + +Action Mailer is released under the MIT license. + + +== Support + +API documentation is at + +* http://api.rubyonrails.com + +Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here: + +* https://github.com/rails/rails/issues + diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer.rb new file mode 100644 index 0000000..b9e682b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer.rb @@ -0,0 +1,51 @@ +#-- +# Copyright (c) 2004-2011 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +actionpack_path = File.expand_path('../../../actionpack/lib', __FILE__) +$:.unshift(actionpack_path) if File.directory?(actionpack_path) && !$:.include?(actionpack_path) + +require 'abstract_controller' +require 'action_view' +require 'action_mailer/version' + +# Common Active Support usage in Action Mailer +require 'active_support/core_ext/class' +require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/array/uniq_by' +require 'active_support/core_ext/module/attr_internal' +require 'active_support/core_ext/module/delegation' +require 'active_support/core_ext/string/inflections' +require 'active_support/lazy_load_hooks' + +module ActionMailer + extend ::ActiveSupport::Autoload + + autoload :AdvAttrAccessor + autoload :Collector + autoload :Base + autoload :DeliveryMethods + autoload :MailHelper + autoload :OldApi + autoload :TestCase + autoload :TestHelper +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/adv_attr_accessor.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/adv_attr_accessor.rb new file mode 100644 index 0000000..c1aa802 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/adv_attr_accessor.rb @@ -0,0 +1,28 @@ +module ActionMailer + module AdvAttrAccessor #:nodoc: + def adv_attr_accessor(name, deprecation=nil) + ivar = "@#{name}" + deprecation ||= "Please pass :#{name} as hash key to mail() instead" + + class_eval <<-ACCESSORS, __FILE__, __LINE__ + 1 + def #{name}=(value) + ActiveSupport::Deprecation.warn "#{name}= is deprecated. #{deprecation}" + #{ivar} = value + end + + def #{name}(*args) + raise ArgumentError, "expected 0 or 1 parameters" unless args.length <= 1 + if args.empty? + ActiveSupport::Deprecation.warn "#{name}() is deprecated and will be removed in future versions." + #{ivar} if instance_variable_names.include?(#{ivar.inspect}) + else + ActiveSupport::Deprecation.warn "#{name}(value) is deprecated. #{deprecation}" + #{ivar} = args.first + end + end + ACCESSORS + + self.protected_instance_variables << ivar if self.respond_to?(:protected_instance_variables) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/base.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/base.rb new file mode 100644 index 0000000..c7d6d59 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/base.rb @@ -0,0 +1,753 @@ +require 'mail' +require 'action_mailer/tmail_compat' +require 'action_mailer/collector' +require 'active_support/core_ext/array/wrap' +require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/proc' +require 'active_support/core_ext/string/inflections' +require 'active_support/core_ext/hash/except' +require 'action_mailer/log_subscriber' + +module ActionMailer #:nodoc: + # Action Mailer allows you to send email from your application using a mailer model and views. + # + # = Mailer Models + # + # To use Action Mailer, you need to create a mailer model. + # + # $ rails generate mailer Notifier + # + # The generated model inherits from ActionMailer::Base. Emails are defined by creating methods + # within the model which are then used to set variables to be used in the mail template, to + # change options on the mail, or to add attachments. + # + # Examples: + # + # class Notifier < ActionMailer::Base + # default :from => 'no-reply@example.com', + # :return_path => 'system@example.com' + # + # def welcome(recipient) + # @account = recipient + # mail(:to => recipient.email_address_with_name, + # :bcc => ["bcc@example.com", "Order Watcher "]) + # end + # end + # + # Within the mailer method, you have access to the following methods: + # + # * attachments[]= - Allows you to add attachments to your email in an intuitive + # manner; attachments['filename.png'] = File.read('path/to/filename.png') + # + # * attachments.inline[]= - Allows you to add an inline attachment to your email + # in the same manner as attachments[]= + # + # * headers[]= - Allows you to specify any header field in your email such + # as headers['X-No-Spam'] = 'True'. Note, while most fields like To: + # From: can only appear once in an email header, other fields like X-Anything + # can appear multiple times. If you want to change a field that can appear multiple times, + # you need to set it to nil first so that Mail knows you are replacing it and not adding + # another field of the same name. + # + # * headers(hash) - Allows you to specify multiple headers in your email such + # as headers({'X-No-Spam' => 'True', 'In-Reply-To' => '1234@message.id'}) + # + # * mail - Allows you to specify email to be sent. + # + # The hash passed to the mail method allows you to specify any header that a Mail::Message + # will accept (any valid Email header including optional fields). + # + # The mail method, if not passed a block, will inspect your views and send all the views with + # the same name as the method, so the above action would send the +welcome.text.erb+ view + # file as well as the +welcome.text.html.erb+ view file in a +multipart/alternative+ email. + # + # If you want to explicitly render only certain templates, pass a block: + # + # mail(:to => user.email) do |format| + # format.text + # format.html + # end + # + # The block syntax is also useful in providing information specific to a part: + # + # mail(:to => user.email) do |format| + # format.text(:content_transfer_encoding => "base64") + # format.html + # end + # + # Or even to render a special view: + # + # mail(:to => user.email) do |format| + # format.text + # format.html { render "some_other_template" } + # end + # + # = Mailer views + # + # Like Action Controller, each mailer class has a corresponding view directory in which each + # method of the class looks for a template with its name. + # + # To define a template to be used with a mailing, create an .erb file with the same + # name as the method in your mailer model. For example, in the mailer defined above, the template at + # app/views/notifier/welcome.text.erb would be used to generate the email. + # + # Variables defined in the model are accessible as instance variables in the view. + # + # Emails by default are sent in plain text, so a sample view for our model example might look like this: + # + # Hi <%= @account.name %>, + # Thanks for joining our service! Please check back often. + # + # You can even use Action Pack helpers in these views. For example: + # + # You got a new note! + # <%= truncate(@note.body, :length => 25) %> + # + # If you need to access the subject, from or the recipients in the view, you can do that through message object: + # + # You got a new note from <%= message.from %>! + # <%= truncate(@note.body, :length => 25) %> + # + # + # = Generating URLs + # + # URLs can be generated in mailer views using url_for or named routes. Unlike controllers from + # Action Pack, the mailer instance doesn't have any context about the incoming request, so you'll need + # to provide all of the details needed to generate a URL. + # + # When using url_for you'll need to provide the :host, :controller, and :action: + # + # <%= url_for(:host => "example.com", :controller => "welcome", :action => "greeting") %> + # + # When using named routes you only need to supply the :host: + # + # <%= users_url(:host => "example.com") %> + # + # You should use the named_route_url style (which generates absolute URLs) and avoid using the + # named_route_path style (which generates relative URLs), since clients reading the mail will + # have no concept of a current URL from which to determine a relative path. + # + # It is also possible to set a default host that will be used in all mailers by setting the :host + # option as a configuration option in config/application.rb: + # + # config.action_mailer.default_url_options = { :host => "example.com" } + # + # Setting ActionMailer::Base.default_url_options directly is now deprecated, use the configuration + # option mentioned above to set the default host. + # + # If you do decide to set a default :host for your mailers you want to use the + # :only_path => false option when using url_for. This will ensure that absolute URLs are + # generated because the url_for view helper will, by default, generate relative URLs when a + # :host option isn't explicitly provided. + # + # = Sending mail + # + # Once a mailer action and template are defined, you can deliver your message or create it and save it + # for delivery later: + # + # Notifier.welcome(david).deliver # sends the email + # mail = Notifier.welcome(david) # => a Mail::Message object + # mail.deliver # sends the email + # + # You never instantiate your mailer class. Rather, you just call the method you defined on the class itself. + # + # = Multipart Emails + # + # Multipart messages can also be used implicitly because Action Mailer will automatically detect and use + # multipart templates, where each template is named after the name of the action, followed by the content + # type. Each such detected template will be added as a separate part to the message. + # + # For example, if the following templates exist: + # * signup_notification.text.erb + # * signup_notification.text.html.erb + # * signup_notification.text.xml.builder + # * signup_notification.text.yaml.erb + # + # Each would be rendered and added as a separate part to the message, with the corresponding content + # type. The content type for the entire message is automatically set to multipart/alternative, + # which indicates that the email contains multiple different representations of the same email + # body. The same instance variables defined in the action are passed to all email templates. + # + # Implicit template rendering is not performed if any attachments or parts have been added to the email. + # This means that you'll have to manually add each part to the email and set the content type of the email + # to multipart/alternative. + # + # = Attachments + # + # Sending attachment in emails is easy: + # + # class ApplicationMailer < ActionMailer::Base + # def welcome(recipient) + # attachments['free_book.pdf'] = File.read('path/to/file.pdf') + # mail(:to => recipient, :subject => "New account information") + # end + # end + # + # Which will (if it had both a welcome.text.erb and welcome.text.html.erb + # template in the view directory), send a complete multipart/mixed email with two parts, + # the first part being a multipart/alternative with the text and HTML email parts inside, + # and the second being a application/pdf with a Base64 encoded copy of the file.pdf book + # with the filename +free_book.pdf+. + # + # = Inline Attachments + # + # You can also specify that a file should be displayed inline with other HTML. This is useful + # if you want to display a corporate logo or a photo. + # + # class ApplicationMailer < ActionMailer::Base + # def welcome(recipient) + # attachments.inline['photo.png'] = File.read('path/to/photo.png') + # mail(:to => recipient, :subject => "Here is what we look like") + # end + # end + # + # And then to reference the image in the view, you create a welcome.html.erb file and + # make a call to +image_tag+ passing in the attachment you want to display and then call + # +url+ on the attachment to get the relative content id path for the image source: + # + #

    Please Don't Cringe

    + # + # <%= image_tag attachments['photo.png'].url -%> + # + # As we are using Action View's +image_tag+ method, you can pass in any other options you want: + # + #

    Please Don't Cringe

    + # + # <%= image_tag attachments['photo.png'].url, :alt => 'Our Photo', :class => 'photo' -%> + # + # = Observing and Intercepting Mails + # + # Action Mailer provides hooks into the Mail observer and interceptor methods. These allow you to + # register objects that are called during the mail delivery life cycle. + # + # An observer object must implement the :delivered_email(message) method which will be + # called once for every email sent after the email has been sent. + # + # An interceptor object must implement the :delivering_email(message) method which will be + # called before the email is sent, allowing you to make modifications to the email before it hits + # the delivery agents. Your object should make any needed modifications directly to the passed + # in Mail::Message instance. + # + # = Default Hash + # + # Action Mailer provides some intelligent defaults for your emails, these are usually specified in a + # default method inside the class definition: + # + # class Notifier < ActionMailer::Base + # default :sender => 'system@example.com' + # end + # + # You can pass in any header value that a Mail::Message accepts. Out of the box, + # ActionMailer::Base sets the following: + # + # * :mime_version => "1.0" + # * :charset => "UTF-8", + # * :content_type => "text/plain", + # * :parts_order => [ "text/plain", "text/enriched", "text/html" ] + # + # parts_order and charset are not actually valid Mail::Message header fields, + # but Action Mailer translates them appropriately and sets the correct values. + # + # As you can pass in any header, you need to either quote the header as a string, or pass it in as + # an underscored symbol, so the following will work: + # + # class Notifier < ActionMailer::Base + # default 'Content-Transfer-Encoding' => '7bit', + # :content_description => 'This is a description' + # end + # + # Finally, Action Mailer also supports passing Proc objects into the default hash, so you + # can define methods that evaluate as the message is being generated: + # + # class Notifier < ActionMailer::Base + # default 'X-Special-Header' => Proc.new { my_method } + # + # private + # + # def my_method + # 'some complex call' + # end + # end + # + # Note that the proc is evaluated right at the start of the mail message generation, so if you + # set something in the defaults using a proc, and then set the same thing inside of your + # mailer method, it will get over written by the mailer method. + # + # = Configuration options + # + # These options are specified on the class level, like + # ActionMailer::Base.raise_delivery_errors = true + # + # * default - You can pass this in at a class level as well as within the class itself as + # per the above section. + # + # * logger - the logger is used for generating information on the mailing run if available. + # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. + # + # * smtp_settings - Allows detailed configuration for :smtp delivery method: + # * :address - Allows you to use a remote mail server. Just change it from its default + # "localhost" setting. + # * :port - On the off chance that your mail server doesn't run on port 25, you can change it. + # * :domain - If you need to specify a HELO domain, you can do it here. + # * :user_name - If your mail server requires authentication, set the username in this setting. + # * :password - If your mail server requires authentication, set the password in this setting. + # * :authentication - If your mail server requires authentication, you need to specify the + # authentication type here. + # This is a symbol and one of :plain (will send the password in the clear), :login (will + # send password Base64 encoded) or :cram_md5 (combines a Challenge/Response mechanism to exchange + # information and a cryptographic Message Digest 5 algorithm to hash important information) + # * :enable_starttls_auto - When set to true, detects if STARTTLS is enabled in your SMTP server + # and starts to use it. + # * :openssl_verify_mode - When using TLS, you can set how OpenSSL checks the certificate. This is + # really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name + # of an OpenSSL verify constant ('none', 'peer', 'client_once','fail_if_no_peer_cert') or directly the + # constant (OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER,...). + # + # * sendmail_settings - Allows you to override options for the :sendmail delivery method. + # * :location - The location of the sendmail executable. Defaults to /usr/sbin/sendmail. + # * :arguments - The command line arguments. Defaults to -i -t with -f sender@address + # added automatically before the message is sent. + # + # * file_settings - Allows you to override options for the :file delivery method. + # * :location - The directory into which emails will be written. Defaults to the application + # tmp/mails. + # + # * raise_delivery_errors - Whether or not errors should be raised if the email fails to be delivered. + # + # * delivery_method - Defines a delivery method. Possible values are :smtp (default), + # :sendmail, :test, and :file. Or you may provide a custom delivery method + # object eg. MyOwnDeliveryMethodClass.new. See the Mail gem documentation on the interface you need to + # implement for a custom delivery agent. + # + # * perform_deliveries - Determines whether emails are actually sent from Action Mailer when you + # call .deliver on an mail message or on an Action Mailer method. This is on by default but can + # be turned off to aid in functional testing. + # + # * deliveries - Keeps an array of all the emails sent out through the Action Mailer with + # delivery_method :test. Most useful for unit and functional testing. + # + # * default_charset - This is now deprecated, use the +default+ method above to + # set the default +:charset+. + # + # * default_content_type - This is now deprecated, use the +default+ method above + # to set the default +:content_type+. + # + # * default_mime_version - This is now deprecated, use the +default+ method above + # to set the default +:mime_version+. + # + # * default_implicit_parts_order - This is now deprecated, use the +default+ method above + # to set the default +:parts_order+. Parts Order is used when a message is built implicitly + # (i.e. multiple parts are assembled from templates which specify the content type in their + # filenames) this variable controls how the parts are ordered. + class Base < AbstractController::Base + include DeliveryMethods + abstract! + + include AbstractController::Logger + include AbstractController::Rendering + include AbstractController::Layouts + include AbstractController::Helpers + include AbstractController::Translation + include AbstractController::AssetPaths + + self.protected_instance_variables = %w(@_action_has_layout) + + helper ActionMailer::MailHelper + include ActionMailer::OldApi + + private_class_method :new #:nodoc: + + class_attribute :default_params + self.default_params = { + :mime_version => "1.0", + :charset => "UTF-8", + :content_type => "text/plain", + :parts_order => [ "text/plain", "text/enriched", "text/html" ] + }.freeze + + class << self + # Register one or more Observers which will be notified when mail is delivered. + def register_observers(*observers) + observers.flatten.compact.each { |observer| register_observer(observer) } + end + + # Register one or more Interceptors which will be called before mail is sent. + def register_interceptors(*interceptors) + interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) } + end + + # Register an Observer which will be notified when mail is delivered. + # Either a class or a string can be passed in as the Observer. If a string is passed in + # it will be constantized. + def register_observer(observer) + delivery_observer = (observer.is_a?(String) ? observer.constantize : observer) + Mail.register_observer(delivery_observer) + end + + # Register an Interceptor which will be called before mail is sent. + # Either a class or a string can be passed in as the Interceptor. If a string is passed in + # it will be constantized. + def register_interceptor(interceptor) + delivery_interceptor = (interceptor.is_a?(String) ? interceptor.constantize : interceptor) + Mail.register_interceptor(delivery_interceptor) + end + + def mailer_name + @mailer_name ||= name.underscore + end + attr_writer :mailer_name + alias :controller_path :mailer_name + + def default(value = nil) + self.default_params = default_params.merge(value).freeze if value + default_params + end + + # Receives a raw email, parses it into an email object, decodes it, + # instantiates a new mailer, and passes the email object to the mailer + # object's +receive+ method. If you want your mailer to be able to + # process incoming messages, you'll need to implement a +receive+ + # method that accepts the raw email string as a parameter: + # + # class MyMailer < ActionMailer::Base + # def receive(mail) + # ... + # end + # end + def receive(raw_mail) + ActiveSupport::Notifications.instrument("receive.action_mailer") do |payload| + mail = Mail.new(raw_mail) + set_payload_for_mail(payload, mail) + new.receive(mail) + end + end + + # Wraps an email delivery inside of Active Support Notifications instrumentation. This + # method is actually called by the Mail::Message object itself through a callback + # when you call :deliver on the Mail::Message, calling +deliver_mail+ directly + # and passing a Mail::Message will do nothing except tell the logger you sent the email. + def deliver_mail(mail) #:nodoc: + ActiveSupport::Notifications.instrument("deliver.action_mailer") do |payload| + self.set_payload_for_mail(payload, mail) + yield # Let Mail do the delivery actions + end + end + + def respond_to?(method, include_private = false) #:nodoc: + super || action_methods.include?(method.to_s) + end + + protected + + def set_payload_for_mail(payload, mail) #:nodoc: + payload[:mailer] = name + payload[:message_id] = mail.message_id + payload[:subject] = mail.subject + payload[:to] = mail.to + payload[:from] = mail.from + payload[:bcc] = mail.bcc if mail.bcc.present? + payload[:cc] = mail.cc if mail.cc.present? + payload[:date] = mail.date + payload[:mail] = mail.encoded + end + + def method_missing(method, *args) #:nodoc: + return super unless respond_to?(method) + new(method, *args).message + end + end + + attr_internal :message + + # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer + # will be initialized according to the named method. If not, the mailer will + # remain uninitialized (useful when you only need to invoke the "receive" + # method, for instance). + def initialize(method_name=nil, *args) + super() + @_message = Mail.new + process(method_name, *args) if method_name + end + + def process(*args) #:nodoc: + lookup_context.skip_default_locale! + super + end + + def mailer_name + self.class.mailer_name + end + + # Allows you to pass random and unusual headers to the new +Mail::Message+ object + # which will add them to itself. + # + # headers['X-Special-Domain-Specific-Header'] = "SecretValue" + # + # You can also pass a hash into headers of header field names and values, which + # will then be set on the Mail::Message object: + # + # headers 'X-Special-Domain-Specific-Header' => "SecretValue", + # 'In-Reply-To' => incoming.message_id + # + # The resulting Mail::Message will have the following in it's header: + # + # X-Special-Domain-Specific-Header: SecretValue + def headers(args=nil) + if args + @_message.headers(args) + else + @_message + end + end + + # Allows you to add attachments to an email, like so: + # + # mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg') + # + # If you do this, then Mail will take the file name and work out the mime type + # set the Content-Type, Content-Disposition, Content-Transfer-Encoding and + # base64 encode the contents of the attachment all for you. + # + # You can also specify overrides if you want by passing a hash instead of a string: + # + # mail.attachments['filename.jpg'] = {:mime_type => 'application/x-gzip', + # :content => File.read('/path/to/filename.jpg')} + # + # If you want to use a different encoding than Base64, you can pass an encoding in, + # but then it is up to you to pass in the content pre-encoded, and don't expect + # Mail to know how to decode this data: + # + # file_content = SpecialEncode(File.read('/path/to/filename.jpg')) + # mail.attachments['filename.jpg'] = {:mime_type => 'application/x-gzip', + # :encoding => 'SpecialEncoding', + # :content => file_content } + # + # You can also search for specific attachments: + # + # # By Filename + # mail.attachments['filename.jpg'] # => Mail::Part object or nil + # + # # or by index + # mail.attachments[0] # => Mail::Part (first attachment) + # + def attachments + @_message.attachments + end + + # The main method that creates the message and renders the email templates. There are + # two ways to call this method, with a block, or without a block. + # + # Both methods accept a headers hash. This hash allows you to specify the most used headers + # in an email message, these are: + # + # * :subject - The subject of the message, if this is omitted, Action Mailer will + # ask the Rails I18n class for a translated :subject in the scope of + # [:actionmailer, mailer_scope, action_name] or if this is missing, will translate the + # humanized version of the action_name + # * :to - Who the message is destined for, can be a string of addresses, or an array + # of addresses. + # * :from - Who the message is from + # * :cc - Who you would like to Carbon-Copy on this email, can be a string of addresses, + # or an array of addresses. + # * :bcc - Who you would like to Blind-Carbon-Copy on this email, can be a string of + # addresses, or an array of addresses. + # * :reply_to - Who to set the Reply-To header of the email to. + # * :date - The date to say the email was sent on. + # + # You can set default values for any of the above headers (except :date) by using the default + # class method: + # + # class Notifier < ActionMailer::Base + # self.default :from => 'no-reply@test.lindsaar.net', + # :bcc => 'email_logger@test.lindsaar.net', + # :reply_to => 'bounces@test.lindsaar.net' + # end + # + # If you need other headers not listed above, you can either pass them in + # as part of the headers hash or use the headers['name'] = value + # method. + # + # When a :return_path is specified as header, that value will be used as the 'envelope from' + # address for the Mail message. Setting this is useful when you want delivery notifications + # sent to a different address than the one in :from. Mail will actually use the + # :return_path in preference to the :sender in preference to the :from + # field for the 'envelope from' value. + # + # If you do not pass a block to the +mail+ method, it will find all templates in the + # view paths using by default the mailer name and the method name that it is being + # called from, it will then create parts for each of these templates intelligently, + # making educated guesses on correct content type and sequence, and return a fully + # prepared Mail::Message ready to call :deliver on to send. + # + # For example: + # + # class Notifier < ActionMailer::Base + # default :from => 'no-reply@test.lindsaar.net', + # + # def welcome + # mail(:to => 'mikel@test.lindsaar.net') + # end + # end + # + # Will look for all templates at "app/views/notifier" with name "welcome". However, those + # can be customized: + # + # mail(:template_path => 'notifications', :template_name => 'another') + # + # And now it will look for all templates at "app/views/notifications" with name "another". + # + # If you do pass a block, you can render specific templates of your choice: + # + # mail(:to => 'mikel@test.lindsaar.net') do |format| + # format.text + # format.html + # end + # + # You can even render text directly without using a template: + # + # mail(:to => 'mikel@test.lindsaar.net') do |format| + # format.text { render :text => "Hello Mikel!" } + # format.html { render :text => "

    Hello Mikel!

    " } + # end + # + # Which will render a multipart/alternative email with text/plain and + # text/html parts. + # + # The block syntax also allows you to customize the part headers if desired: + # + # mail(:to => 'mikel@test.lindsaar.net') do |format| + # format.text(:content_transfer_encoding => "base64") + # format.html + # end + # + def mail(headers={}, &block) + # Guard flag to prevent both the old and the new API from firing + # Should be removed when old API is removed + @mail_was_called = true + m = @_message + + # At the beginning, do not consider class default for parts order neither content_type + content_type = headers[:content_type] + parts_order = headers[:parts_order] + + # Call all the procs (if any) + default_values = self.class.default.merge(self.class.default) do |k,v| + v.respond_to?(:call) ? v.bind(self).call : v + end + + # Handle defaults + headers = headers.reverse_merge(default_values) + headers[:subject] ||= default_i18n_subject + + # Apply charset at the beginning so all fields are properly quoted + m.charset = charset = headers[:charset] + + # Set configure delivery behavior + wrap_delivery_behavior!(headers.delete(:delivery_method)) + + # Assign all headers except parts_order, content_type and body + assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path) + assignable.each { |k, v| m[k] = v } + + # Render the templates and blocks + responses, explicit_order = collect_responses_and_parts_order(headers, &block) + create_parts_from_responses(m, responses) + + # Setup content type, reapply charset and handle parts order + m.content_type = set_content_type(m, content_type, headers[:content_type]) + m.charset = charset + + if m.multipart? + parts_order ||= explicit_order || headers[:parts_order] + m.body.set_sort_order(parts_order) + m.body.sort_parts! + end + + m + end + + protected + + def set_content_type(m, user_content_type, class_default) + params = m.content_type_parameters || {} + case + when user_content_type.present? + user_content_type + when m.has_attachments? + if m.attachments.detect { |a| a.inline? } + ["multipart", "related", params] + else + ["multipart", "mixed", params] + end + when m.multipart? + ["multipart", "alternative", params] + else + m.content_type || class_default + end + end + + # Translates the +subject+ using Rails I18n class under [:actionmailer, mailer_scope, action_name] scope. + # If it does not find a translation for the +subject+ under the specified scope it will default to a + # humanized version of the action_name. + def default_i18n_subject #:nodoc: + mailer_scope = self.class.mailer_name.gsub('/', '.') + I18n.t(:subject, :scope => [mailer_scope, action_name], :default => action_name.humanize) + end + + def collect_responses_and_parts_order(headers) #:nodoc: + responses, parts_order = [], nil + + if block_given? + collector = ActionMailer::Collector.new(lookup_context) { render(action_name) } + yield(collector) + parts_order = collector.responses.map { |r| r[:content_type] } + responses = collector.responses + elsif headers[:body] + responses << { + :body => headers.delete(:body), + :content_type => self.class.default[:content_type] || "text/plain" + } + else + templates_path = headers.delete(:template_path) || self.class.mailer_name + templates_name = headers.delete(:template_name) || action_name + + each_template(templates_path, templates_name) do |template| + self.formats = template.formats + + responses << { + :body => render(:template => template), + :content_type => template.mime_type.to_s + } + end + end + + [responses, parts_order] + end + + def each_template(paths, name, &block) #:nodoc: + templates = lookup_context.find_all(name, Array.wrap(paths)) + templates.uniq_by { |t| t.formats }.each(&block) + end + + def create_parts_from_responses(m, responses) #:nodoc: + if responses.size == 1 && !m.has_attachments? + responses[0].each { |k,v| m[k] = v } + elsif responses.size > 1 && m.has_attachments? + container = Mail::Part.new + container.content_type = "multipart/alternative" + responses.each { |r| insert_part(container, r, m.charset) } + m.add_part(container) + else + responses.each { |r| insert_part(m, r, m.charset) } + end + end + + def insert_part(container, response, charset) #:nodoc: + response[:charset] ||= charset + part = Mail::Part.new(response) + container.add_part(part) + end + + ActiveSupport.run_load_hooks(:action_mailer, self) + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/collector.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/collector.rb new file mode 100644 index 0000000..d03e085 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/collector.rb @@ -0,0 +1,30 @@ +require 'abstract_controller/collector' +require 'active_support/core_ext/hash/reverse_merge' +require 'active_support/core_ext/array/extract_options' + +module ActionMailer #:nodoc: + class Collector + include AbstractController::Collector + attr_reader :responses + + def initialize(context, &block) + @context = context + @responses = [] + @default_render = block + end + + def any(*args, &block) + options = args.extract_options! + raise "You have to supply at least one format" if args.empty? + args.each { |type| send(type, options.dup, &block) } + end + alias :all :any + + def custom(mime, options={}) + options.reverse_merge!(:content_type => mime.to_s) + @context.freeze_formats([mime.to_sym]) + options[:body] = block_given? ? yield : @default_render.call + @responses << options + end + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/delivery_methods.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/delivery_methods.rb new file mode 100644 index 0000000..d1467fb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/delivery_methods.rb @@ -0,0 +1,86 @@ +require 'tmpdir' + +module ActionMailer + # This module handles everything related to mail delivery, from registering new + # delivery methods to configuring the mail object to be sent. + module DeliveryMethods + extend ActiveSupport::Concern + + included do + class_attribute :delivery_methods, :delivery_method + + # Do not make this inheritable, because we always want it to propagate + cattr_accessor :raise_delivery_errors + self.raise_delivery_errors = true + + cattr_accessor :perform_deliveries + self.perform_deliveries = true + + self.delivery_methods = {}.freeze + self.delivery_method = :smtp + + add_delivery_method :smtp, Mail::SMTP, + :address => "localhost", + :port => 25, + :domain => 'localhost.localdomain', + :user_name => nil, + :password => nil, + :authentication => nil, + :enable_starttls_auto => true + + add_delivery_method :file, Mail::FileDelivery, + :location => defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails" + + add_delivery_method :sendmail, Mail::Sendmail, + :location => '/usr/sbin/sendmail', + :arguments => '-i -t' + + add_delivery_method :test, Mail::TestMailer + end + + module ClassMethods + # Provides a list of emails that have been delivered by Mail::TestMailer + delegate :deliveries, :deliveries=, :to => Mail::TestMailer + + # Adds a new delivery method through the given class using the given symbol + # as alias and the default options supplied: + # + # Example: + # + # add_delivery_method :sendmail, Mail::Sendmail, + # :location => '/usr/sbin/sendmail', + # :arguments => '-i -t' + # + def add_delivery_method(symbol, klass, default_options={}) + class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings") + send(:"#{symbol}_settings=", default_options) + self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze + end + + def wrap_delivery_behavior(mail, method=nil) #:nodoc: + method ||= self.delivery_method + mail.delivery_handler = self + + case method + when NilClass + raise "Delivery method cannot be nil" + when Symbol + if klass = delivery_methods[method.to_sym] + mail.delivery_method(klass, send(:"#{method}_settings")) + else + raise "Invalid delivery method #{method.inspect}" + end + else + mail.delivery_method(method) + end + + mail.perform_deliveries = perform_deliveries + mail.raise_delivery_errors = raise_delivery_errors + end + end + + def wrap_delivery_behavior!(*args) #:nodoc: + self.class.wrap_delivery_behavior(message, *args) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/log_subscriber.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/log_subscriber.rb new file mode 100644 index 0000000..7ba57b1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/log_subscriber.rb @@ -0,0 +1,22 @@ +require 'active_support/core_ext/array/wrap' + +module ActionMailer + class LogSubscriber < ActiveSupport::LogSubscriber + def deliver(event) + recipients = Array.wrap(event.payload[:to]).join(', ') + info("\nSent mail to #{recipients} (%1.fms)" % event.duration) + debug(event.payload[:mail]) + end + + def receive(event) + info("\nReceived mail (%.1fms)" % event.duration) + debug(event.payload[:mail]) + end + + def logger + ActionMailer::Base.logger + end + end +end + +ActionMailer::LogSubscriber.attach_to :action_mailer \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/mail_helper.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/mail_helper.rb new file mode 100644 index 0000000..6f22adc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/mail_helper.rb @@ -0,0 +1,56 @@ +module ActionMailer + module MailHelper + # Uses Text::Format to take the text and format it, indented two spaces for + # each line, and wrapped at 72 columns. + def block_format(text) + formatted = text.split(/\n\r\n/).collect { |paragraph| + format_paragraph(paragraph) + }.join("\n") + + # Make list points stand on their own line + formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" } + formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" } + + formatted + end + + # Access the mailer instance. + def mailer + @_controller + end + + # Access the message instance. + def message + @_message + end + + # Access the message attachments list. + def attachments + @_message.attachments + end + + # Returns +text+ wrapped at +len+ columns and indented +indent+ spaces. + # + # === Examples + # + # my_text = "Here is a sample text with more than 40 characters" + # + # format_paragraph(my_text, 25, 4) + # # => " Here is a sample text with\n more than 40 characters" + def format_paragraph(text, len = 72, indent = 2) + sentences = [[]] + + text.split.each do |word| + if (sentences.last + [word]).join(' ').length > len + sentences << [word] + else + sentences.last << word + end + end + + sentences.map { |sentence| + "#{" " * indent}#{sentence.join(' ')}" + }.join "\n" + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/old_api.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/old_api.rb new file mode 100644 index 0000000..bfa9499 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/old_api.rb @@ -0,0 +1,255 @@ +require 'active_support/concern' +require 'active_support/core_ext/object/try' +require 'active_support/core_ext/object/blank' + +module ActionMailer + module OldApi #:nodoc: + extend ActiveSupport::Concern + + included do + extend ActionMailer::AdvAttrAccessor + self.protected_instance_variables.concat %w(@parts @mail_was_called @headers) + + # Specify the BCC addresses for the message + adv_attr_accessor :bcc + + # Specify the CC addresses for the message. + adv_attr_accessor :cc + + # Specify the charset to use for the message. This defaults to the + # +default_charset+ specified for ActionMailer::Base. + adv_attr_accessor :charset + + # Specify the content type for the message. This defaults to text/plain + # in most cases, but can be automatically set in some situations. + adv_attr_accessor :content_type + + # Specify the from address for the message. + adv_attr_accessor :from + + # Specify the address (if different than the "from" address) to direct + # replies to this message. + adv_attr_accessor :reply_to + + # Specify the order in which parts should be sorted, based on content-type. + # This defaults to the value for the +default_implicit_parts_order+. + adv_attr_accessor :implicit_parts_order + + # Defaults to "1.0", but may be explicitly given if needed. + adv_attr_accessor :mime_version + + # The recipient addresses for the message, either as a string (for a single + # address) or an array (for multiple addresses). + adv_attr_accessor :recipients, "Please pass :to as hash key to mail() instead" + + # The date on which the message was sent. If not set (the default), the + # header will be set by the delivery agent. + adv_attr_accessor :sent_on, "Please pass :date as hash key to mail() instead" + + # Specify the subject of the message. + adv_attr_accessor :subject + + # Specify the template name to use for current message. This is the "base" + # template name, without the extension or directory, and may be used to + # have multiple mailer methods share the same template. + adv_attr_accessor :template, "Please pass :template_name or :template_path as hash key to mail() instead" + + # Define the body of the message. This is either a Hash (in which case it + # specifies the variables to pass to the template when it is rendered), + # or a string, in which case it specifies the actual text of the message. + adv_attr_accessor :body + end + + def process(method_name, *args) + initialize_defaults(method_name) + super + unless @mail_was_called + create_parts + create_mail + end + @_message + end + + # Add a part to a multipart message, with the given content-type. The + # part itself is yielded to the block so that other properties (charset, + # body, headers, etc.) can be set on it. + def part(params) + ActiveSupport::Deprecation.warn "part() is deprecated and will be removed in future versions. " << + "Please pass a block to mail() instead." + params = {:content_type => params} if String === params + + if custom_headers = params.delete(:headers) + params.merge!(custom_headers) + end + + part = Mail::Part.new(params) + + yield part if block_given? + @parts << part + end + + # Add an attachment to a multipart message. This is simply a part with the + # content-disposition set to "attachment". + def attachment(params, &block) + ActiveSupport::Deprecation.warn "attachment() is deprecated and will be removed in future versions. " << + "Please use the attachments[] API instead." + params = { :content_type => params } if String === params + + params[:content] ||= params.delete(:data) || params.delete(:body) + + if params[:filename] + params = normalize_file_hash(params) + else + params = normalize_nonfile_hash(params) + end + + part(params, &block) + end + + protected + + def normalize_nonfile_hash(params) + content_disposition = "attachment;" + + mime_type = params.delete(:mime_type) + + if content_type = params.delete(:content_type) + content_type = "#{mime_type || content_type};" + end + + params[:body] = params.delete(:data) if params[:data] + + { :content_type => content_type, + :content_disposition => content_disposition }.merge(params) + end + + def normalize_file_hash(params) + filename = File.basename(params.delete(:filename)) + content_disposition = "attachment; filename=\"#{File.basename(filename)}\"" + + mime_type = params.delete(:mime_type) + + if (content_type = params.delete(:content_type)) && (content_type !~ /filename=/) + content_type = "#{mime_type || content_type}; filename=\"#{filename}\"" + end + + params[:body] = params.delete(:data) if params[:data] + + { :content_type => content_type, + :content_disposition => content_disposition }.merge(params) + end + + def create_mail + m = @_message + + set_fields!({:subject => @subject, :to => @recipients, :from => @from, + :bcc => @bcc, :cc => @cc, :reply_to => @reply_to}, @charset) + + m.mime_version = @mime_version if @mime_version + m.date = @sent_on.to_time rescue @sent_on if @sent_on + + @headers.each { |k, v| m[k] = v } + + real_content_type, ctype_attrs = parse_content_type + main_type, sub_type = split_content_type(real_content_type) + + if @parts.size == 1 && @parts.first.parts.empty? + m.content_type([main_type, sub_type, ctype_attrs]) + m.body = @parts.first.body.encoded + else + @parts.each do |p| + m.add_part(p) + end + + m.body.set_sort_order(@implicit_parts_order) + m.body.sort_parts! + + if real_content_type =~ /multipart/ + ctype_attrs.delete "charset" + m.content_type([main_type, sub_type, ctype_attrs]) + end + end + + wrap_delivery_behavior! + m.content_transfer_encoding = '8bit' unless m.body.only_us_ascii? + + @_message + end + + # Set up the default values for the various instance variables of this + # mailer. Subclasses may override this method to provide different + # defaults. + def initialize_defaults(method_name) + @charset ||= self.class.default[:charset].try(:dup) + @content_type ||= self.class.default[:content_type].try(:dup) + @implicit_parts_order ||= self.class.default[:parts_order].try(:dup) + @mime_version ||= self.class.default[:mime_version].try(:dup) + + @cc, @bcc, @reply_to, @subject, @from, @recipients = nil, nil, nil, nil, nil, nil + + @mailer_name ||= self.class.mailer_name.dup + @template ||= method_name + @mail_was_called = false + + @parts ||= [] + @headers ||= {} + @sent_on ||= Time.now + @body ||= {} + end + + def create_parts + if String === @body + @parts.unshift create_inline_part(@body) + elsif @parts.empty? || @parts.all? { |p| p.content_disposition =~ /^attachment/ } + lookup_context.find_all(@template, [@mailer_name]).each do |template| + self.formats = template.formats + @parts << create_inline_part(render(:template => template), template.mime_type) + end + + if @parts.size > 1 + @content_type = "multipart/alternative" if @content_type !~ /^multipart/ + end + + # If this is a multipart e-mail add the mime_version if it is not + # already set. + @mime_version ||= "1.0" unless @parts.empty? + end + end + + def create_inline_part(body, mime_type=nil) + ct = mime_type || "text/plain" + main_type, sub_type = split_content_type(ct.to_s) + + Mail::Part.new( + :content_type => [main_type, sub_type, {:charset => charset}], + :content_disposition => "inline", + :body => body + ) + end + + def set_fields!(headers, charset) #:nodoc: + m = @_message + m.charset = charset + m.subject ||= headers.delete(:subject) if headers[:subject] + m.to ||= headers.delete(:to) if headers[:to] + m.from ||= headers.delete(:from) if headers[:from] + m.cc ||= headers.delete(:cc) if headers[:cc] + m.bcc ||= headers.delete(:bcc) if headers[:bcc] + m.reply_to ||= headers.delete(:reply_to) if headers[:reply_to] + end + + def split_content_type(ct) + ct.to_s.split("/") + end + + def parse_content_type + if @content_type.blank? + [ nil, {} ] + else + ctype, *attrs = @content_type.split(/;\s*/) + attrs = Hash[attrs.map { |attr| attr.split(/=/, 2) }] + [ctype, {"charset" => @charset}.merge!(attrs)] + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/railtie.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/railtie.rb new file mode 100644 index 0000000..444754d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/railtie.rb @@ -0,0 +1,43 @@ +require "action_mailer" +require "rails" +require "abstract_controller/railties/routes_helpers" + +module ActionMailer + class Railtie < Rails::Railtie + config.action_mailer = ActiveSupport::OrderedOptions.new + + initializer "action_mailer.logger" do + ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger } + end + + initializer "action_mailer.set_configs" do |app| + paths = app.config.paths + options = app.config.action_mailer + + options.assets_dir ||= paths["public"].first + options.javascripts_dir ||= paths["public/javascripts"].first + options.stylesheets_dir ||= paths["public/stylesheets"].first + + # make sure readers methods get compiled + options.asset_path ||= app.config.asset_path + options.asset_host ||= app.config.asset_host + + ActiveSupport.on_load(:action_mailer) do + include AbstractController::UrlFor + extend ::AbstractController::Railties::RoutesHelpers.with(app.routes) + include app.routes.mounted_helpers + + register_interceptors(options.delete(:interceptors)) + register_observers(options.delete(:observers)) + + options.each { |k,v| send("#{k}=", v) } + end + end + + initializer "action_mailer.compile_config_methods" do + ActiveSupport.on_load(:action_mailer) do + config.compile_methods! if config.respond_to?(:compile_methods!) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/test_case.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/test_case.rb new file mode 100644 index 0000000..63e1814 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/test_case.rb @@ -0,0 +1,79 @@ +require 'active_support/core_ext/class/attribute' + +module ActionMailer + class NonInferrableMailerError < ::StandardError + def initialize(name) + super "Unable to determine the mailer to test from #{name}. " + + "You'll need to specify it using tests YourMailer in your " + + "test case definition" + end + end + + class TestCase < ActiveSupport::TestCase + module Behavior + extend ActiveSupport::Concern + + include TestHelper + + module ClassMethods + def tests(mailer) + self._mailer_class = mailer + end + + def mailer_class + if mailer = self._mailer_class + mailer + else + tests determine_default_mailer(name) + end + end + + def determine_default_mailer(name) + name.sub(/Test$/, '').constantize + rescue NameError + raise NonInferrableMailerError.new(name) + end + end + + module InstanceMethods + + protected + + def initialize_test_deliveries + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries.clear + end + + def set_expected_mail + @expected = Mail.new + @expected.content_type ["text", "plain", { "charset" => charset }] + @expected.mime_version = '1.0' + end + + private + + def charset + "UTF-8" + end + + def encode(subject) + Mail::Encodings.q_value_encode(subject, charset) + end + + def read_fixture(action) + IO.readlines(File.join(Rails.root, 'test', 'fixtures', self.class.mailer_class.name.underscore, action)) + end + end + + included do + class_attribute :_mailer_class + setup :initialize_test_deliveries + setup :set_expected_mail + end + end + + include Behavior + + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/test_helper.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/test_helper.rb new file mode 100644 index 0000000..5beab87 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/test_helper.rb @@ -0,0 +1,61 @@ +module ActionMailer + module TestHelper + extend ActiveSupport::Concern + + # Asserts that the number of emails sent matches the given number. + # + # def test_emails + # assert_emails 0 + # ContactMailer.deliver_contact + # assert_emails 1 + # ContactMailer.deliver_contact + # assert_emails 2 + # end + # + # If a block is passed, that block should cause the specified number of emails to be sent. + # + # def test_emails_again + # assert_emails 1 do + # ContactMailer.deliver_contact + # end + # + # assert_emails 2 do + # ContactMailer.deliver_contact + # ContactMailer.deliver_contact + # end + # end + def assert_emails(number) + if block_given? + original_count = ActionMailer::Base.deliveries.size + yield + new_count = ActionMailer::Base.deliveries.size + assert_equal original_count + number, new_count, "#{number} emails expected, but #{new_count - original_count} were sent" + else + assert_equal number, ActionMailer::Base.deliveries.size + end + end + + # Assert that no emails have been sent. + # + # def test_emails + # assert_no_emails + # ContactMailer.deliver_contact + # assert_emails 1 + # end + # + # If a block is passed, that block should not cause any emails to be sent. + # + # def test_emails_again + # assert_no_emails do + # # No emails should be sent from this block + # end + # end + # + # Note: This assertion is simply a shortcut for: + # + # assert_emails 0 + def assert_no_emails(&block) + assert_emails 0, &block + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/tmail_compat.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/tmail_compat.rb new file mode 100644 index 0000000..1b2cdcf --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/tmail_compat.rb @@ -0,0 +1,37 @@ +module Mail + class Message + + def set_content_type(*args) + message = 'Message#set_content_type is deprecated, please just call ' << + 'Message#content_type with the same arguments' + ActiveSupport::Deprecation.warn(message, caller[0,2]) + content_type(*args) + end + + alias :old_transfer_encoding :transfer_encoding + def transfer_encoding(value = nil) + if value + message = 'Message#transfer_encoding is deprecated, ' << + 'please call Message#content_transfer_encoding with the same arguments' + ActiveSupport::Deprecation.warn(message, caller[0,2]) + content_transfer_encoding(value) + else + old_transfer_encoding + end + end + + def transfer_encoding=(value) + message = 'Message#transfer_encoding= is deprecated, ' << + 'please call Message#content_transfer_encoding= with the same arguments' + ActiveSupport::Deprecation.warn(message, caller[0,2]) + self.content_transfer_encoding = value + end + + def original_filename + message = 'Message#original_filename is deprecated, please call Message#filename' + ActiveSupport::Deprecation.warn(message, caller[0,2]) + filename + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/version.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/version.rb new file mode 100644 index 0000000..242e9fa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/action_mailer/version.rb @@ -0,0 +1,10 @@ +module ActionMailer + module VERSION #:nodoc: + MAJOR = 3 + MINOR = 1 + TINY = 1 + PRE = nil + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/USAGE b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/USAGE new file mode 100644 index 0000000..448ddbd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/USAGE @@ -0,0 +1,18 @@ +Description: +============ + Stubs out a new mailer and its views. Pass the mailer name, either + CamelCased or under_scored, and an optional list of emails as arguments. + + This generates a mailer class in app/mailers and invokes your template + engine and test framework generators. + +Example: +======== + rails generate mailer Notifications signup forgot_password invoice + + creates a Notifications mailer class, views, test, and fixtures: + Mailer: app/mailers/notifications.rb + Views: app/views/notifications/signup.erb [...] + Test: test/functional/notifications_test.rb + Fixtures: test/fixtures/notifications/signup [...] + diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/mailer_generator.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/mailer_generator.rb new file mode 100644 index 0000000..dd7fa64 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/mailer_generator.rb @@ -0,0 +1,16 @@ +module Rails + module Generators + class MailerGenerator < NamedBase + source_root File.expand_path("../templates", __FILE__) + + argument :actions, :type => :array, :default => [], :banner => "method method" + check_class_collision + + def create_mailer_file + template "mailer.rb", File.join('app/mailers', class_path, "#{file_name}.rb") + end + + hook_for :template_engine, :test_framework + end + end +end diff --git a/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/templates/mailer.rb b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/templates/mailer.rb new file mode 100644 index 0000000..aaa1f79 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionmailer-3.1.1/lib/rails/generators/mailer/templates/mailer.rb @@ -0,0 +1,18 @@ +<% module_namespacing do -%> +class <%= class_name %> < ActionMailer::Base + default <%= key_value :from, '"from@example.com"' %> +<% actions.each do |action| -%> + + # Subject can be set in your I18n file at config/locales/en.yml + # with the following lookup: + # + # en.<%= file_path.gsub("/",".") %>.<%= action %>.subject + # + def <%= action %> + @greeting = "Hi" + + mail <%= key_value :to, '"to@example.org"' %> + end +<% end -%> +end +<% end -%> diff --git a/vendor/ruby/1.9.1/gems/actionpack-3.1.1/CHANGELOG b/vendor/ruby/1.9.1/gems/actionpack-3.1.1/CHANGELOG new file mode 100644 index 0000000..9aa4a7f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/actionpack-3.1.1/CHANGELOG @@ -0,0 +1,5663 @@ +*Rails 3.1.1 (unreleased)* + +* stylesheet_link_tag('/stylesheets/application') and similar helpers doesn't +throw Sprockets::FileOutsidePaths exception anymore [Santiago Pastorino] + +* Ensure default_asset_host_protocol is respected, closes #2980. [José Valim] + + Changing rake db:schema:dump to run :environment as well as :load_config, + as running :load_config alone will lead to the dumper being run without + including extensions such as those included in foreigner and + spatial_adapter. + + This reverses a change made here: + https://github.com/rails/rails/commit/5df72a238e9fcb18daf6ab6e6dc9051c9106d7bb#L0L324 + + I'm assuming here that :load_config needs to be invoked + separately from :environment, as it is elsewhere in the + file for db operations, if not the alternative is to go + back to "task :dump => :environment do". + + [Ben Woosley] + +* Update to rack-cache 1.1. + + Versions prior to 1.1 delete the If-Modified-Since and If-Not-Modified + headers when config.action_controller.perform_caching is true. This has two + problems: + * unexpected inconsistent behaviour between development & + production environments + * breaks applications that use of these headers + + [Brendan Ribera] + +* Ensure that enhancements to assets:precompile task are only run once [Sam Pohlenz] + +* TestCase should respect the view_assigns API instead of pulling variables on +its own. [José Valim] + +* javascript_path and stylesheet_path now refer to /assets if asset pipelining +is on. [Santiago Pastorino] + +* button_to support form option. Now you're able to pass for example +'data-type' => 'json'. [ihower] + +* image_path and image_tag should use /assets if asset pipelining is turned +on. Closes #3126 [Santiago Pastorino and christos] + +* Avoid use of existing precompiled assets during rake assets:precompile run. +Closes #3119 [Guillermo Iguaran] + +* Copy assets to nondigested filenames too [Santiago Pastorino] + +* Give precedence to `config.digest = false` over the existence of +manifest.yml asset digests [christos] + +* escape options for the stylesheet_link_tag method [Alexey Vakhov] + +* Re-launch assets:precompile task using (Rake.)ruby instead of Kernel.exec so +it works on Windows [cablegram] + +* env var passed to process shouldn't be modified in process method. [Santiago +Pastorino] + +* `rake assets:precompile` loads the application but does not initialize +it. + + To the app developer, this means configuration add in + config/initializers/* will not be executed. + + Plugins developers need to special case their initializers that are + meant to be run in the assets group by adding :group => :assets. [José Valim] + +* Sprockets uses config.assets.prefix for asset_path [asee] + +* FileStore key_file_path properly limit filenames to 255 characters. [phuibonhoa] + +* Fix Hash#to_query edge case with html_safe strings. [brainopia] + +* Allow asset tag helper methods to accept :digest => false option in order to completely avoid the digest generation. +Useful for linking assets from static html files or from emails when the user +could probably look at an older html email with an older asset. [Santiago Pastorino] + +* Don't mount Sprockets server at config.assets.prefix if config.assets.compile is false. [Mark J. Titorenko] + +* Set relative url root in assets when controller isn't available for Sprockets (eg. Sass files using asset_path). Fixes #2435 [Guillermo Iguaran] + +* Fix basic auth credential generation to not make newlines. GH #2882 + +* Fixed the behavior of asset pipeline when config.assets.digest and config.assets.compile are false and requested asset isn't precompiled. + Before the requested asset were compiled anyway ignoring that the config.assets.compile flag is false. [Guillermo Iguaran] + +* CookieJar is now Enumerable. Fixes #2795 + +* Fixed AssetNotPrecompiled error raised when rake assets:precompile is compiling certain .erb files. See GH #2763 #2765 #2805 [Guillermo Iguaran] + +* Manifest is correctly placed in assets path when default assets prefix is changed. Fixes #2776 [Guillermo Iguaran] + +* Fixed stylesheet_link_tag and javascript_include_tag to respect additional options passed by the users when debug is on. [Guillermo Iguaran] + +* Fix ActiveRecord#exists? when passsed a nil value + +* Fix assert_select_email to work on multipart and non-multipart emails as the method stopped working correctly in Rails 3.x due to changes in the new mail gem. + + +*Rails 3.1.0 (August 30, 2011)* + +* Param values are `paramified` in controller tests. [David Chelimsky] + +* x_sendfile_header now defaults to nil and config/environments/production.rb doesn't set a particular value for it. This allows servers to set it through X-Sendfile-Type. [Santiago Pastorino] + +* The submit form helper does not generate an id "object_name_id" anymore. [fbrusatti] + +* Make sure respond_with with :js tries to render a template in all cases [José Valim] + +* json_escape will now return a SafeBuffer string if it receives SafeBuffer string [tenderlove] + +* Make sure escape_js returns SafeBuffer string if it receives SafeBuffer string [Prem Sichanugrist] + +* Fix escape_js to work correctly with the new SafeBuffer restriction [Paul Gallagher] + +* Brought back alternative convention for namespaced models in i18n [thoefer] + + Now the key can be either "namespace.model" or "namespace/model" until further deprecation. + +* It is prohibited to perform a in-place SafeBuffer mutation [tenderlove] + + The old behavior of SafeBuffer allowed you to mutate string in place via + method like `sub!`. These methods can add unsafe strings to a safe buffer, + and the safe buffer will continue to be marked as safe. + + An example problem would be something like this: + + <%= link_to('hello world', @user).sub!(/hello/, params[:xss]) %> + + In the above example, an untrusted string (`params[:xss]`) is added to the + safe buffer returned by `link_to`, and the untrusted content is successfully + sent to the client without being escaped. To prevent this from happening + `sub!` and other similar methods will now raise an exception when they are called on a safe buffer. + + In addition to the in-place versions, some of the versions of these methods which return a copy of the string will incorrectly mark strings as safe. For example: + + <%= link_to('hello world', @user).sub(/hello/, params[:xss]) %> + + The new versions will now ensure that *all* strings returned by these methods on safe buffers are marked unsafe. + + You can read more about this change in http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2e516e7acc96c4fb + +* Warn if we cannot verify CSRF token authenticity [José Valim] + +* Allow AM/PM format in datetime selectors [Aditya Sanghi] + +* Only show dump of regular env methods on exception screen (not all the rack crap) [DHH] + +* auto_link has been removed with no replacement. If you still use auto_link + please install the rails_autolink gem: + http://github.com/tenderlove/rails_autolink + + [tenderlove] + +* Added streaming support, you can enable it with: [José Valim] + + class PostsController < ActionController::Base + stream :only => :index + end + + Please read the docs at `ActionController::Streaming` for more information. + +* Added `ActionDispatch::Request.ignore_accept_header` to ignore accept headers and only consider the format given as parameter [José Valim] + +* Created `ActionView::Renderer` and specified an API for `ActionView::Context`, check those objects for more information [José Valim] + +* Added `ActionController::ParamsWrapper` to wrap parameters into a nested hash, and will be turned on for JSON request in new applications by default [Prem Sichanugrist] + + This can be customized by setting `ActionController::Base.wrap_parameters` in `config/initializer/wrap_parameters.rb` + +* RJS has been extracted out to a gem. [fxn] + +* Implicit actions named not_implemented can be rendered. [Santiago Pastorino] + +* Wildcard route will always match the optional format segment by default. [Prem Sichanugrist] + + For example if you have this route: + + map '*pages' => 'pages#show' + + by requesting '/foo/bar.json', your `params[:pages]` will be equals to "foo/bar" with the request format of JSON. If you want the old 3.0.x behavior back, you could supply `:format => false` like this: + + map '*pages' => 'pages#show', :format => false + +* Added Base.http_basic_authenticate_with to do simple http basic authentication with a single class method call [DHH] + + class PostsController < ApplicationController + USER_NAME, PASSWORD = "dhh", "secret" + + before_filter :authenticate, :except => [ :index ] + + def index + render :text => "Everyone can see me!" + end + + def edit + render :text => "I'm only accessible if you know the password" + end + + private + def authenticate + authenticate_or_request_with_http_basic do |user_name, password| + user_name == USER_NAME && password == PASSWORD + end + end + end + + ..can now be written as + + class PostsController < ApplicationController + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index + + def index + render :text => "Everyone can see me!" + end + + def edit + render :text => "I'm only accessible if you know the password" + end + end + +* Allow you to add `force_ssl` into controller to force browser to transfer data via HTTPS protocol on that particular controller. You can also specify `:only` or `:except` to specific it to particular action. [DHH and Prem Sichanugrist] + +* Allow FormHelper#form_for to specify the :method as a direct option instead of through the :html hash [DHH] + + form_for(@post, remote: true, method: :delete) instead of form_for(@post, remote: true, html: { method: :delete }) + +* Make JavaScriptHelper#j() an alias for JavaScriptHelper#escape_javascript() -- note this then supersedes the Object#j() method that the JSON gem adds within templates using the JavaScriptHelper [DHH] + +* Sensitive query string parameters (specified in config.filter_parameters) will now be filtered out from the request paths in the log file. [Prem Sichanugrist, fxn] + +* URL parameters which return false for to_param now appear in the query string (previously they were removed) [Andrew White] + +* URL parameters which return nil for to_param are now removed from the query string [Andrew White] + +* ActionDispatch::MiddlewareStack now uses composition over inheritance. It is +no longer an array which means there may be methods missing that were not +tested. + +* Add an :authenticity_token option to form_tag for custom handling or to omit the token (pass :authenticity_token => false). [Jakub Kuźma, Igor Wiedler] + +* HTML5 button_tag helper. [Rizwan Reza] + +* Template lookup now searches further up in the inheritance chain. [Artemave] + +* Brought back config.action_view.cache_template_loading, which allows to decide whether templates should be cached or not. [Piotr Sarnacki] + +* url_for and named url helpers now accept :subdomain and :domain as options, [Josh Kalderimis] + +* The redirect route method now also accepts a hash of options which will only change the parts of the url in question, or an object which responds to call, allowing for redirects to be reused (check the documentation for examples). [Josh Kalderimis] + +* Added config.action_controller.include_all_helpers. By default 'helper :all' is done in ActionController::Base, which includes all the helpers by default. Setting include_all_helpers to false will result in including only application_helper and helper corresponding to controller (like foo_helper for foo_controller). [Piotr Sarnacki] + +* Added a convenience idiom to generate HTML5 data-* attributes in tag helpers from a :data hash of options: + + tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)}) + # =>
    + + Keys are dasherized. Values are JSON-encoded, except for strings and symbols. [Stephen Celis] + +* Deprecate old template handler API. The new API simply requires a template handler to respond to call. [José Valim] + +* :rhtml and :rxml were finally removed as template handlers. [José Valim] + +* Moved etag responsibility from ActionDispatch::Response to the middleware stack. [José Valim] + +* Rely on Rack::Session stores API for more compatibility across the Ruby world. This is backwards incompatible since Rack::Session expects #get_session to accept 4 arguments and requires #destroy_session instead of simply #destroy. [José Valim] + +* file_field automatically adds :multipart => true to the enclosing form. [Santiago Pastorino] + +* Renames csrf_meta_tag -> csrf_meta_tags, and aliases csrf_meta_tag for backwards compatibility. [fxn] + +* Add Rack::Cache to the default stack. Create a Rails store that delegates to the Rails cache, so by default, whatever caching layer you are using will be used for HTTP caching. Note that Rack::Cache will be used if you use #expires_in, #fresh_when or #stale with :public => true. Otherwise, the caching rules will apply to the browser only. [Yehuda Katz, Carl Lerche] + + +*Rails 3.0.7 (April 18, 2011)* + +*No changes. + + +*Rails 3.0.6 (April 5, 2011) + +* Fixed XSS vulnerability in `auto_link`. `auto_link` no longer marks input as + html safe. Please make sure that calls to auto_link() are wrapped in a + sanitize(), or a raw() depending on the type of input passed to auto_link(). + For example: + + <%= sanitize(auto_link(some_user_input)) %> + + Thanks to Torben Schulz for reporting this. The fix can be found here: + 61ee3449674c591747db95f9b3472c5c3bd9e84d + +* Fixes the output of `rake routes` to be correctly match to the behavior of the application, as the regular expression used to match the path is greedy and won't capture the format part by default [Prem Sichanugrist] + +* Fixes an issue with number_to_human when converting values which are less than 1 but greater than -1 [Josh Kalderimis] + +* Sensitive query string parameters (specified in config.filter_parameters) will now be filtered out from the request paths in the log file. [Prem Sichanugrist, fxn] + +* URL parameters which return nil for to_param are now removed from the query string [Andrew White] + +* Don't allow i18n to change the minor version, version now set to ~> 0.5.0 [Santiago Pastorino] + +* Make TranslationHelper#translate use the :rescue_format option in I18n 0.5.0 [Sven Fuchs] + +* Fix regression: javascript_include_tag shouldn't raise if you register an expansion key with nil or [] value [Santiago Pastorino] + +* Fix Action caching bug where an action that has a non-cacheable response always renders a nil response body. It now correctly renders the response body. [Cheah Chu Yeow] + + +*Rails 3.0.5 (February 26, 2011)* + +* No changes. + + +*Rails 3.0.4 (February 8, 2011)* + +* No changes. + + +*Rails 3.0.3 (November 16, 2010)* + +* When ActiveRecord::Base objects are sent to predicate methods, the id of the object should be sent to ARel, not the ActiveRecord::Base object. + +* :constraints routing should only do sanity checks against regular expressions. String arguments are OK. + + +*Rails 3.0.2 (November 15, 2010)* + +* The helper number_to_currency accepts a new :negative_format option to be able to configure how to render negative amounts. [Don Wilson] + + +*Rails 3.0.1 (October 15, 2010)* + +* No Changes, just a version bump. + + +*Rails 3.0.0 (August 29, 2010)* + +* password_field renders with nil value by default making the use of passwords secure by default, if you want to render you should do for instance f.password_field(:password, :value => @user.password) [Santiago Pastorino] + +* Symbols and strings in routes should yield the same behavior. Note this may break existing apps that were using symbols with the new routes API. [José Valim] + +* Add clear_helpers as a way to clean up all helpers added to this controller, maintaining just the helper with the same name as the controller. [José Valim] + +* Support routing constraints in functional tests. [Andrew White] + +* Add a header that tells Internet Explorer (all versions) to use the best available standards support. [Yehuda Katz] + +* Allow stylesheet/javascript extensions to be changed through railties. [Josh Kalderimis] + +* link_to, button_to, and tag/tag_options now rely on html_escape instead of escape_once. [fxn] + +* url_for returns always unescaped strings, and the :escape option is gone. [fxn] + +* Added accept-charset parameter and _snowman hidden field to force the contents + of Rails POSTed forms to be in UTF-8 [Yehuda Katz] + +* Upgrade to Rack 1.2.1 [Jeremy Kemper] + +* Allow :path to be given to match/get/post/put/delete instead of :path_names in the new router [Carlos Antônio da Silva] + +* Added resources_path_names to the new router DSL [José Valim] + +* Allow options to be given to the namespace method in the new router [Carlos Antônio da Silva] + +* Deprecate :name_prefix in the new router DSL [José Valim] + +* Add shallow routes back to the new router [Diego Carrion, Andrew White] + + resources :posts do + shallow do + resources :comments + end + end + + You can now use comment_path for /comments/1 instead of post_comment_path for /posts/1/comments/1. + +* Add support for multi-subdomain session by setting cookie host in session cookie so you can share session between www.example.com, example.com and user.example.com. #4818 [Guillermo Ãlvarez] + +* Removed textilize, textilize_without_paragraph and markdown helpers. [Santiago Pastorino] + +* Remove middleware laziness [José Valim] + +* Make session stores rely on request.cookie_jar and change set_session semantics to return the cookie value instead of a boolean. [José Valim] + +* OAuth 2: HTTP Token Authorization support to complement Basic and Digest Authorization. [Rick Olson] + +* Fixed inconsistencies in form builder and view helpers #4432 [Neeraj Singh] + +* Both :xml and :json renderers now forwards the given options to the model, allowing you to invoke them as render :xml => @projects, :include => :tasks [José Valim, Yehuda Katz] + +* Renamed the field error CSS class from fieldWithErrors to field_with_errors for consistency. [Jeremy Kemper] + +* Add support for shorthand routes like /projects/status(.:format) #4423 [Diego Carrion] + +* Changed translate helper so that it doesn’t mark every translation as safe HTML. Only keys with a "_html" suffix and keys named "html" are considered to be safe HTML. All other translations are left untouched. [Craig Davey] + +* New option :as added to form_for allows to change the object name. The old <% form_for :client, @post %> becomes <% form_for @post, :as => :client %> [spastorino] + +* Removed verify method in controllers. [JV] + It's now available as a plugin at http://github.com/rails/verification + +* Removed input, form, error_messages_for and error_message_on from views. [JV] + It's now available as a plugin at http://github.com/rails/dynamic_form + +* Routes can be scoped by controller module. [Jeremy Kemper] + + # /session => Auth::SessionsController + scope :module => 'auth' do + resource :session + end + +* Added #favicon_link_tag, it uses #image_path so in particular the favicon gets an asset ID [fxn] + +* Fixed that default locale templates should be used if the current locale template is missing [DHH] + +* Added all the new HTML5 form types as individual form tag methods (search, url, number, etc) #3646 [Stephen Celis] + +* Changed the object used in routing constraints to be an instance of + ActionDispatch::Request rather than Rack::Request [YK] + +* Changed ActionDispatch::Request#method to return a String, to be compatible + with Rack::Request. Added ActionDispatch::Request#method_symbol to + return a symbol form of the request method. [YK] + +* Changed ActionDispatch::Request#method to return the original + method and #request_method to return the overridden method in the + case of methodoverride being used (this means that #method returns + "HEAD" and #request_method returns "GET" in HEAD requests). This + is for compatibility with Rack::Request [YK] + +* #concat is now deprecated in favor of using <%= %> helpers [YK] + +* Block helpers now return Strings, so you can use <%= form_for @foo do |f| %>. + <% form_for do |f| %> still works with deprecation notices [YK] + +* Add a new #mount method on the router that does not anchor the PATH_INFO + at the end [YK & CL] + +* Create a new LookupContext object that is responsible for performantly + finding a template for a given pattern [JV] + +* Removed relative_url_for in favor of respecting SCRIPT_NAME [YK & CL] + +* Changed file streaming to use Rack::Sendfile middleware [YK] + +* ActionDispatch::Request#content_type returns a String to be compatible with + Rack::Request. Use #content_mime_type for the Mime::Type instance [YK] + +* Updated Prototype to 1.6.1 and Scriptaculous to 1.8.3 [ML] + +* Change the preferred way that URL helpers are included into a class[YK & CL] + + # for all helpers including named routes + include Rails.application.router.url_helpers + + # for just url_for + include Rails.application.router.url_for + +* Fixed that PrototypeHelper#update_page should return html_safe [DHH] + +* Fixed that much of DateHelper wouldn't return html_safe? strings [DHH] + +* Fixed that fragment caching should return a cache hit as html_safe (or it would all just get escaped) [DHH] + +* Added that ActionController::Base now does helper :all instead of relying on the default ApplicationController in Rails to do it [DHH] + +* Added ActionDispatch::Request#authorization to access the http authentication header regardless of its proxy hiding [DHH] + +* Added :alert, :notice, and :flash as options to ActionController::Base#redirect_to that'll automatically set the proper flash before the redirection [DHH]. Examples: + + flash[:notice] = 'Post was created' + redirect_to(@post) + + ...becomes: + + redirect_to(@post, :notice => 'Post was created') + +* Added ActionController::Base#notice/= and ActionController::Base#alert/= as a convenience accessors in both the controller and the view for flash[:notice]/= and flash[:alert]/= [DHH] + + +* Introduce grouped_collection_select helper. #1249 [Dan Codeape, Erik Ostrom] + +* Make sure javascript_include_tag/stylesheet_link_tag does not append ".js" or ".css" onto external urls. #1664 [Matthew Rudy Jacobs] + +* Ruby 1.9: fix Content-Length for multibyte send_data streaming. #2661 [Sava Chankov] + +* Ruby 1.9: ERB template encoding using a magic comment at the top of the file. [Jeremy Kemper] + <%# encoding: utf-8 %> + +* Change integration test helpers to accept Rack environment instead of just HTTP Headers [Pratik Naik] + + Before : get '/path', {}, 'Accept' => 'text/javascript' + After : get '/path', {}, 'HTTP_ACCEPT' => 'text/javascript' + +* Instead of checking Rails.env.test? in Failsafe middleware, check env["rails.raise_exceptions"] [Bryan Helmkamp] + +* Fixed that TestResponse.cookies was returning cookies unescaped #1867 [Doug McInnes] + + +*2.3.2 [Final] (March 15, 2009)* + +* Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #") [DHH] + +* Don't check authenticity tokens for any AJAX requests [Ross Kaffenberger/Bryan Helmkamp] + +* Added ability to pass in :public => true to fresh_when, stale?, and expires_in to make the request proxy cachable #2095 [Gregg Pollack] + +* Fixed that passing a custom form builder would be forwarded to nested fields_for calls #2023 [Eloy Duran/Nate Wiger] + +* Form option helpers now support disabled option tags and the use of lambdas for selecting/disabling option tags from collections #837 [Tekin] + +* Added partial scoping to TranslationHelper#translate, so if you call translate(".foo") from the people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo") [DHH] + +* Fix a syntax error in current_page?() that was prevent matches against URL's with multiple query parameters #1385, #1868 [chris finne/Andrew White] + +* Added localized rescue template when I18n.locale is set (ex: public/404.da.html) #1835 [José Valim] + +* Make the form_for and fields_for helpers support the new Active Record nested update options. #1202 [Eloy Duran] + + <% form_for @person do |person_form| %> + ... + <% person_form.fields_for :projects do |project_fields| %> + <% if project_fields.object.active? %> + Name: <%= project_fields.text_field :name %> + <% end %> + <% end %> + <% end %> + + +* Added grouped_options_for_select helper method for wrapping option tags in optgroups. #977 [Jon Crawford] + +* Implement HTTP Digest authentication. #1230 [Gregg Kellogg, Pratik Naik] Example : + + class DummyDigestController < ActionController::Base + USERS = { "lifo" => 'world' } + + before_filter :authenticate + + def index + render :text => "Hello Secret" + end + + private + + def authenticate + authenticate_or_request_with_http_digest("Super Secret") do |username| + # Return the user's password + USERS[username] + end + end + end + +* Improved i18n support for the number_to_human_size helper. Changes the storage_units translation data; update your translations accordingly. #1634 [Yaroslav Markin] + storage_units: + # %u is the storage unit, %n is the number (default: 2 MB) + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + +* Added :silence option to BenchmarkHelper#benchmark and turned log_level into a hash parameter and deprecated the old use [DHH] + +* Fixed the AssetTagHelper cache to use the computed asset host as part of the cache key instead of just assuming the its a string #1299 [DHH] + +* Make ActionController#render(string) work as a shortcut for render :file/:template/:action => string. [#1435] [Pratik Naik] Examples: + + # Instead of render(:action => 'other_action') + render('other_action') # argument has no '/' + render(:other_action) + + # Instead of render(:template => 'controller/action') + render('controller/action') # argument must not begin with a '/', but contain a '/' + + # Instead of render(:file => '/Users/lifo/home.html.erb') + render('/Users/lifo/home.html.erb') # argument must begin with a '/' + +* Add :prompt option to date/time select helpers. #561 [Sam Oliver] + +* Fixed that send_file shouldn't set an etag #1578 [Hongli Lai] + +* Allow users to opt out of the spoofing checks in Request#remote_ip. Useful for sites whose traffic regularly triggers false positives. [Darren Boyd] + +* Deprecated formatted_polymorphic_url. [Jeremy Kemper] + +* Added the option to declare an asset_host as an object that responds to call (see http://github.com/dhh/asset-hosting-with-minimum-ssl for an example) [David Heinemeier Hansson] + +* Added support for multiple routes.rb files (useful for plugin engines). This also means that draw will no longer clear the route set, you have to do that by hand (shouldn't make a difference to you unless you're doing some funky stuff) [David Heinemeier Hansson] + +* Dropped formatted_* routes in favor of just passing in :format as an option. This cuts resource routes generation in half #1359 [aaronbatalion] + +* Remove support for old double-encoded cookies from the cookie store. These values haven't been generated since before 2.1.0, and any users who have visited the app in the intervening 6 months will have had their cookie upgraded. [Michael Koziarski] + +* Allow helpers directory to be overridden via ActionController::Base.helpers_dir #1424 [Sam Pohlenz] + +* Remove deprecated ActionController::Base#assign_default_content_type_and_charset + +* Changed the default of ActionView#render to assume partials instead of files when not given an options hash [David Heinemeier Hansson]. Examples: + + # Instead of <%= render :partial => "account" %> + <%= render "account" %> + + # Instead of <%= render :partial => "account", :locals => { :account => @buyer } %> + <%= render "account", :account => @buyer %> + + # @account is an Account instance, so it uses the RecordIdentifier to replace + # <%= render :partial => "accounts/account", :locals => { :account => @account } %> + <%= render(@account) %> + + # @posts is an array of Post instances, so it uses the RecordIdentifier to replace + # <%= render :partial => "posts/post", :collection => @posts %> + <%= render(@posts) %> + +* Remove deprecated render_component. Please use the plugin from http://github.com/rails/render_component/tree/master [Pratik Naik] + +* Fixed RedCloth and BlueCloth shouldn't preload. Instead just assume that they're available if you want to use textilize and markdown and let autoload require them [David Heinemeier Hansson] + + +*2.2.2 (November 21st, 2008)* + +* I18n: translate number_to_human_size. Add storage_units: [Bytes, KB, MB, GB, TB] to your translations. #1448 [Yaroslav Markin] + +* Restore backwards compatible functionality for setting relative_url_root. Include deprecation + +* Switched the CSRF module to use the request content type to decide if the request is forgeable. #1145 [Jeff Cohen] + +* Added :only and :except to map.resources to let people cut down on the number of redundant routes in an application. Typically only useful for huge routesets. #1215 [Tom Stuart] + + map.resources :products, :only => :show do |product| + product.resources :images, :except => :destroy + end + +* Added render :js for people who want to render inline JavaScript replies without using RJS [David Heinemeier Hansson] + +* Fixed that polymorphic_url should compact given array #1317 [hiroshi] + +* Fixed the sanitize helper to avoid double escaping already properly escaped entities #683 [antonmos/Ryan McGeary] + +* Fixed that FormTagHelper generated illegal html if name contained square brackets #1238 [Vladimir Dobriakov] + +* Fix regression bug that made date_select and datetime_select raise a Null Pointer Exception when a nil date/datetime was passed and only month and year were displayed #1289 [Bernardo Padua/Tor Erik] + +* Simplified the logging format for parameters (don't include controller, action, and format as duplicates) [David Heinemeier Hansson] + +* Remove the logging of the Session ID when the session store is CookieStore [David Heinemeier Hansson] + +* Fixed regex in redirect_to to fully support URI schemes #1247 [Seth Fitzsimmons] + +* Fixed bug with asset timestamping when using relative_url_root #1265 [Joe Goldwasser] + + +*2.2.0 [RC1] (October 24th, 2008)* + +* Fix incorrect closing CDATA delimiter and that HTML::Node.parse would blow up on unclosed CDATA sections [packagethief] + +* Added stale? and fresh_when methods to provide a layer of abstraction above request.fresh? and friends [David Heinemeier Hansson]. Example: + + class ArticlesController < ApplicationController + def show_with_respond_to_block + @article = Article.find(params[:id]) + + + # If the request sends headers that differs from the options provided to stale?, then + # the request is indeed stale and the respond_to block is triggered (and the options + # to the stale? call is set on the response). + # + # If the request headers match, then the request is fresh and the respond_to block is + # not triggered. Instead the default render will occur, which will check the last-modified + # and etag headers and conclude that it only needs to send a "304 Not Modified" instead + # of rendering the template. + if stale?(:last_modified => @article.published_at.utc, :etag => @article) + respond_to do |wants| + # normal response processing + end + end + end + + def show_with_implied_render + @article = Article.find(params[:id]) + + # Sets the response headers and checks them against the request, if the request is stale + # (i.e. no match of either etag or last-modified), then the default render of the template happens. + # If the request is fresh, then the default render will return a "304 Not Modified" + # instead of rendering the template. + fresh_when(:last_modified => @article.published_at.utc, :etag => @article) + end + end + + +* Added inline builder yield to atom_feed_helper tags where appropriate [Sam Ruby]. Example: + + entry.summary :type => 'xhtml' do |xhtml| + xhtml.p pluralize(order.line_items.count, "line item") + xhtml.p "Shipped to #{order.address}" + xhtml.p "Paid by #{order.pay_type}" + end + +* Make PrototypeHelper#submit_to_remote a wrapper around PrototypeHelper#button_to_remote. [Tarmo Tänav] + +* Set HttpOnly for the cookie session store's cookie. #1046 + +* Added FormTagHelper#image_submit_tag confirm option #784 [Alastair Brunton] + +* Fixed FormTagHelper#submit_tag with :disable_with option wouldn't submit the button's value when was clicked #633 [Jose Fernandez] + +* Stopped logging template compiles as it only clogs up the log [David Heinemeier Hansson] + +* Changed the X-Runtime header to report in milliseconds [David Heinemeier Hansson] + +* Changed BenchmarkHelper#benchmark to report in milliseconds [David Heinemeier Hansson] + +* Changed logging format to be millisecond based and skip misleading stats [David Heinemeier Hansson]. Went from: + + Completed in 0.10000 (4 reqs/sec) | Rendering: 0.04000 (40%) | DB: 0.00400 (4%) | 200 OK [http://example.com] + + ...to: + + Completed in 100ms (View: 40, DB: 4) | 200 OK [http://example.com] + +* Add support for shallow nesting of routes. #838 [S. Brent Faulkner] + + Example : + + map.resources :users, :shallow => true do |user| + user.resources :posts + end + + - GET /users/1/posts (maps to PostsController#index action as usual) + named route "user_posts" is added as usual. + + - GET /posts/2 (maps to PostsController#show action as if it were not nested) + Additionally, named route "post" is added too. + +* Added button_to_remote helper. #3641 [Donald Piret, Tarmo Tänav] + +* Deprecate render_component. Please use render_component plugin from http://github.com/rails/render_component/tree/master [Pratik Naik] + +* Routes may be restricted to lists of HTTP methods instead of a single method or :any. #407 [Brennan Dunn, Gaius Centus Novus] + map.resource :posts, :collection => { :search => [:get, :post] } + map.session 'session', :requirements => { :method => [:get, :post, :delete] } + +* Deprecated implicit local assignments when rendering partials [Josh Peek] + +* Introduce current_cycle helper method to return the current value without bumping the cycle. #417 [Ken Collins] + +* Allow polymorphic_url helper to take url options. #880 [Tarmo Tänav] + +* Switched integration test runner to use Rack processor instead of CGI [Josh Peek] + +* Made AbstractRequest.if_modified_sense return nil if the header could not be parsed [Jamis Buck] + +* Added back ActionController::Base.allow_concurrency flag [Josh Peek] + +* AbstractRequest.relative_url_root is no longer automatically configured by a HTTP header. It can now be set in your configuration environment with config.action_controller.relative_url_root [Josh Peek] + +* Update Prototype to 1.6.0.2 #599 [Patrick Joyce] + +* Conditional GET utility methods. [Jeremy Kemper] + response.last_modified = @post.updated_at + response.etag = [:admin, @post, current_user] + + if request.fresh?(response) + head :not_modified + else + # render ... + end + +* All 2xx requests are considered successful [Josh Peek] + +* Fixed that AssetTagHelper#compute_public_path shouldn't cache the asset_host along with the source or per-request proc's won't run [David Heinemeier Hansson] + +* Removed config.action_view.cache_template_loading, use config.cache_classes instead [Josh Peek] + +* Get buffer for fragment cache from template's @output_buffer [Josh Peek] + +* Set config.action_view.warn_cache_misses = true to receive a warning if you perform an action that results in an expensive disk operation that could be cached [Josh Peek] + +* Refactor template preloading. New abstractions include Renderable mixins and a refactored Template class [Josh Peek] + +* Changed ActionView::TemplateHandler#render API method signature to render(template, local_assigns = {}) [Josh Peek] + +* Changed PrototypeHelper#submit_to_remote to PrototypeHelper#button_to_remote to stay consistent with link_to_remote (submit_to_remote still works as an alias) #8994 [clemens] + +* Add :recursive option to javascript_include_tag and stylesheet_link_tag to be used along with :all. #480 [Damian Janowski] + +* Allow users to disable the use of the Accept header [Michael Koziarski] + + The accept header is poorly implemented by browsers and causes strange + errors when used on public sites where crawlers make requests too. You + can use formatted urls (e.g. /people/1.xml) to support API clients in a + much simpler way. + + To disable the header you need to set: + + config.action_controller.use_accept_header = false + +* Do not stat template files in production mode before rendering. You will no longer be able to modify templates in production mode without restarting the server [Josh Peek] + +* Deprecated TemplateHandler line offset [Josh Peek] + +* Allow caches_action to accept cache store options. #416. [José Valim]. Example: + + caches_action :index, :redirected, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour + +* Remove define_javascript_functions, javascript_include_tag and friends are far superior. [Michael Koziarski] + +* Deprecate :use_full_path render option. The supplying the option no longer has an effect [Josh Peek] + +* Add :as option to render a collection of partials with a custom local variable name. #509 [Simon Jefford, Pratik Naik] + + render :partial => 'other_people', :collection => @people, :as => :person + + This will let you access objects of @people as 'person' local variable inside 'other_people' partial template. + +* time_zone_select: support for regexp matching of priority zones. Resolves #195 [Ernie Miller] + +* Made ActionView::Base#render_file private [Josh Peek] + +* Refactor and simplify the implementation of assert_redirected_to. Arguments are now normalised relative to the controller being tested, not the root of the application. [Michael Koziarski] + + This could cause some erroneous test failures if you were redirecting between controllers + in different namespaces and wrote your assertions relative to the root of the application. + +* Remove follow_redirect from controller functional tests. + + If you want to follow redirects you can use integration tests. The functional test + version was only useful if you were using redirect_to :id=>... + +* Fix polymorphic_url with singleton resources. #461 [Tammer Saleh] + +* Replaced TemplateFinder abstraction with ViewLoadPaths [Josh Peek] + +* Added block-call style to link_to [Sam Stephenson/David Heinemeier Hansson]. Example: + + <% link_to(@profile) do %> + <%= @profile.name %> -- Check it out!! + <% end %> + +* Performance: integration test benchmarking and profiling. [Jeremy Kemper] + +* Make caching more aware of mime types. Ensure request format is not considered while expiring cache. [Jonathan del Strother] + +* Drop ActionController::Base.allow_concurrency flag [Josh Peek] + +* More efficient concat and capture helpers. Remove ActionView::Base.erb_variable. [Jeremy Kemper] + +* Added page.reload functionality. Resolves #277. [Sean Huber] + +* Fixed Request#remote_ip to only raise hell if the HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR doesn't match (not just if they're both present) [Mark Imbriaco, Bradford Folkens] + +* Allow caches_action to accept a layout option [José Valim] + +* Added Rack processor [Ezra Zygmuntowicz, Josh Peek] + + +*2.1.0 (May 31st, 2008)* + +* InstanceTag#default_time_from_options overflows to DateTime [Geoff Buesing] + +* Fixed that forgery protection can be used without session tracking (Peter Jones) [#139] + +* Added session(:on) to turn session management back on in a controller subclass if the superclass turned it off (Peter Jones) [#136] + +* Change the request forgery protection to go by Content-Type instead of request.format so that you can't bypass it by POSTing to "#{request.uri}.xml" [Rick Olson] +* InstanceTag#default_time_from_options with hash args uses Time.current as default; respects hash settings when time falls in system local spring DST gap [Geoff Buesing] + +* select_date defaults to Time.zone.today when config.time_zone is set [Geoff Buesing] + +* Fixed that TextHelper#text_field would corrypt when raw HTML was used as the value (mchenryc, Kevin Glowacz) [#80] + +* Added ActionController::TestCase#rescue_action_in_public! to control whether the action under test should use the regular rescue_action path instead of simply raising the exception inline (great for error testing) [David Heinemeier Hansson] + +* Reduce number of instance variables being copied from controller to view. [Pratik Naik] + +* select_datetime and select_time default to Time.zone.now when config.time_zone is set [Geoff Buesing] + +* datetime_select defaults to Time.zone.now when config.time_zone is set [Geoff Buesing] + +* Remove ActionController::Base#view_controller_internals flag. [Pratik Naik] + +* Add conditional options to caches_page method. [Paul Horsfall] + +* Move missing template logic to ActionView. [Pratik Naik] + +* Introduce ActionView::InlineTemplate class. [Pratik Naik] + +* Automatically parse posted JSON content for Mime::JSON requests. [Rick Olson] + + POST /posts + {"post": {"title": "Breaking News"}} + + def create + @post = Post.create params[:post] + # ... + end + +* add json_escape ERB util to escape html entities in json strings that are output in HTML pages. [Rick Olson] + +* Provide a helper proxy to access helper methods from outside views. Closes #10839 [Josh Peek] + e.g. ApplicationController.helpers.simple_format(text) + +* Improve documentation. [Xavier Noria, leethal, jerome] + +* Ensure RJS redirect_to doesn't html-escapes string argument. Closes #8546 [Josh Peek, eventualbuddha, Pratik Naik] + +* Support render :partial => collection of heterogeneous elements. #11491 [Zach Dennis] + +* Avoid remote_ip spoofing. [Brian Candler] + +* Added support for regexp flags like ignoring case in the :requirements part of routes declarations #11421 [NeilW] + +* Fixed that ActionController::Base#read_multipart would fail if boundary was exactly 10240 bytes #10886 [ariejan] + +* Fixed HTML::Tokenizer (used in sanitize helper) didn't handle unclosed CDATA tags #10071 [esad, packagethief] + +* Improve documentation. [Ryan Bigg, Jan De Poorter, Cheah Chu Yeow, Xavier Shay, Jack Danger Canty, Emilio Tagua, Xavier Noria, Sunny Ripert] + +* Fixed that FormHelper#radio_button would produce invalid ids #11298 [harlancrystal] + +* Added :confirm option to submit_tag #11415 [Emilio Tagua] + +* Fixed NumberHelper#number_with_precision to properly round in a way that works equally on Mac, Windows, Linux (closes #11409, #8275, #10090, #8027) [zhangyuanyi] + +* Allow the #simple_format text_helper to take an html_options hash for each paragraph. #2448 [François Beausoleil, Chris O'Sullivan] + +* Fix regression from filter refactoring where re-adding a skipped filter resulted in it being called twice. [Rick Olson] + +* Refactor filters to use Active Support callbacks. #11235 [Josh Peek] + +* Fixed that polymorphic routes would modify the input array #11363 [thomas.lee] + +* Added :format option to NumberHelper#number_to_currency to enable better localization support #11149 [lylo] + +* Fixed that TextHelper#excerpt would include one character too many #11268 [Irfy] + +* Fix more obscure nested parameter hash parsing bug. #10797 [thomas.lee] + +* Added ActionView::Helpers::register_javascript/stylesheet_expansion to make it easier for plugin developers to inject multiple assets. #10350 [lotswholetime] + +* Fix nested parameter hash parsing bug. #10797 [thomas.lee] + +* Allow using named routes in ActionController::TestCase before any request has been made. Closes #11273 [Eloy Duran] + +* Fixed that sweepers defined by cache_sweeper will be added regardless of the perform_caching setting. Instead, control whether the sweeper should be run with the perform_caching setting. This makes testing easier when you want to turn perform_caching on/off [David Heinemeier Hansson] + +* Make MimeResponds::Responder#any work without explicit types. Closes #11140 [jaw6] + +* Better error message for type conflicts when parsing params. Closes #7962 [spicycode, matt] + +* Remove unused ActionController::Base.template_class. Closes #10787 [Pratik Naik] + +* Moved template handlers related code from ActionView::Base to ActionView::Template. [Pratik Naik] + +* Tests for div_for and content_tag_for helpers. Closes #11223 [Chris O'Sullivan] + +* Allow file uploads in Integration Tests. Closes #11091 [RubyRedRick] + +* Refactor partial rendering into a PartialTemplate class. [Pratik Naik] + +* Added that requests with JavaScript as the priority mime type in the accept header and no format extension in the parameters will be treated as though their format was :js when it comes to determining which template to render. This makes it possible for JS requests to automatically render action.js.rjs files without an explicit respond_to block [David Heinemeier Hansson] + +* Tests for distance_of_time_in_words with TimeWithZone instances. Closes #10914 [Ernesto Jimenez] + +* Remove support for multivalued (e.g., '&'-delimited) cookies. [Jamis Buck] + +* Fix problem with render :partial collections, records, and locals. #11057 [lotswholetime] + +* Added support for naming concrete classes in sweeper declarations [David Heinemeier Hansson] + +* Remove ERB trim variables from trace template in case ActionView::Base.erb_trim_mode is changed in the application. #10098 [Tim Pope, Chris Kampmeier] + +* Fix typo in form_helper documentation. #10650 [Xavier Shay, Chris Kampmeier] + +* Fix bug with setting Request#format= after the getter has cached the value. #10889 [cch1] + +* Correct inconsistencies in RequestForgeryProtection docs. #11032 [Mislav Marohnić] + +* Introduce a Template class to ActionView. #11024 [Pratik Naik] + +* Introduce the :index option for form_for and fields_for to simplify multi-model forms (see http://railscasts.com/episodes/75). #9883 [rmm5t] + +* Introduce map.resources :cards, :as => 'tarjetas' to use a custom resource name in the URL: cards_path == '/tarjetas'. #10578 [blj] + +* TestSession supports indifferent access. #7372 [tamc, Arsen7, mhackett, julik, jean.helou] + +* Make assert_routing aware of the HTTP method used. #8039 [mpalmer] + e.g. assert_routing({ :method => 'put', :path => '/product/321' }, { :controller => "product", :action => "update", :id => "321" }) + +* Make map.root accept a single symbol as an argument to declare an alias. #10818 [bscofield] + + e.g. map.dashboard '/dashboard', :controller=>'dashboard' + map.root :dashboard + +* Handle corner case with image_tag when passed 'messed up' image names. #9018 [Duncan Beevers, mpalmer] + +* Add label_tag helper for generating elements. #10802 [DefV] + +* Introduce TemplateFinder to handle view paths and lookups. #10800 [Pratik Naik] + +* Performance: optimize route recognition. Large speedup for apps with many resource routes. #10835 [oleganza] + +* Make render :partial recognise form builders and use the _form partial. #10814 [Damian Janowski] + +* Allow users to declare other namespaces when using the atom feed helpers. #10304 [david.calavera] + +* Introduce send_file :x_sendfile => true to send an X-Sendfile response header. [Jeremy Kemper] + +* Fixed ActionView::Helpers::ActiveRecordHelper::form for when protect_from_forgery is used #10739 [Jeremy Evans] + +* Provide nicer access to HTTP Headers. Instead of request.env["HTTP_REFERRER"] you can now use request.headers["Referrer"]. [Michael Koziarski] + +* UrlWriter respects relative_url_root. #10748 [Cheah Chu Yeow] + +* The asset_host block takes the controller request as an optional second argument. Example: use a single asset host for SSL requests. #10549 [Cheah Chu Yeow, Peter B, Tom Taylor] + +* Support render :text => nil. #6684 [tjennings, PotatoSalad, Cheah Chu Yeow] + +* assert_response failures include the exception message. #10688 [Seth Rasmussen] + +* All fragment cache keys are now by default prefixed with the "views/" namespace [David Heinemeier Hansson] + +* Moved the caching stores from ActionController::Caching::Fragments::* to ActiveSupport::Cache::*. If you're explicitly referring to a store, like ActionController::Caching::Fragments::MemoryStore, you need to update that reference with ActiveSupport::Cache::MemoryStore [David Heinemeier Hansson] + +* Deprecated ActionController::Base.fragment_cache_store for ActionController::Base.cache_store [David Heinemeier Hansson] + +* Made fragment caching in views work for rjs and builder as well #6642 [Dee Zsombor] + +* Fixed rendering of partials with layout when done from site layout #9209 [antramm] + +* Fix atom_feed_helper to comply with the atom spec. Closes #10672 [Xavier Shay] + + * The tags created do not contain a date (http://feedvalidator.org/docs/error/InvalidTAG.html) + * IDs are not guaranteed unique + * A default self link was not provided, contrary to the documentation + * NOTE: This changes tags for existing atom entries, but at least they validate now. + +* Correct indentation in tests. Closes #10671 [Luca Guidi] + +* Fix that auto_link looks for ='s in url paths (Amazon urls have them). Closes #10640 [Brad Greenlee] + +* Ensure that test case setup is run even if overridden. #10382 [Josh Peek] + +* Fix HTML Sanitizer to allow trailing spaces in CSS style attributes. Closes #10566 [wesley.moxam] + +* Add :default option to time_zone_select. #10590 [Matt Aimonetti] + + +*2.0.2* (December 16th, 2007) + +* Added delete_via_redirect and put_via_redirect to integration testing #10497 [philodespotos] + +* Allow headers['Accept'] to be set by hand when calling xml_http_request #10461 [BMorearty] + +* Added OPTIONS to list of default accepted HTTP methods #10449 [holoway] + +* Added option to pass proc to ActionController::Base.asset_host for maximum configurability #10521 [Cheah Chu Yeow]. Example: + + ActionController::Base.asset_host = Proc.new { |source| + if source.starts_with?('/images') + "http://images.example.com" + else + "http://assets.example.com" + end + } + +* Fixed that ActionView#file_exists? would be incorrect if @first_render is set #10569 [dbussink] + +* Added that Array#to_param calls to_param on all it's elements #10473 [brandon] + +* Ensure asset cache directories are automatically created. #10337 [Josh Peek, Cheah Chu Yeow] + +* render :xml and :json preserve custom content types. #10388 [jmettraux, Cheah Chu Yeow] + +* Refactor Action View template handlers. #10437, #10455 [Josh Peek] + +* Fix DoubleRenderError message and leave out mention of returning false from filters. Closes #10380 [Frederick Cheung] + +* Clean up some cruft around ActionController::Base#head. Closes #10417 [ssoroka] + + +*2.0.1* (December 7th, 2007) + +* Fixed send_file/binary_content for testing #8044 [tolsen] + +* When a NonInferrableControllerError is raised, make the proposed fix clearer in the error message. Closes #10199 [Jack Danger Canty] + +* Update Prototype to 1.6.0.1. [sam] + +* Update script.aculo.us to 1.8.0.1. [madrobby] + +* Add 'disabled' attribute to

+ END + eruby = MyEruby.new(input, :prefixchar=>'%') # default '%' + puts eruby.src + + output: + _buf = ''; _buf << '
    + '; for item in @items + _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • + '; end + % you can indent '%' lines + _buf << '
+ '; + _buf.to_s + + - | + Add helper CGI script. See 'public_html/README.txt' for details. + + - | + Rubinius is supported as first-class Ruby implementation. + + - | + C++ support. Try '-l cpp' command-line option. + + + changes: + + - | + Remove dependency to 'abstract' library. + You don't need to install 'abstract' gem. + + - | + Erubis::Eruby#load_file() now sets cache file timestamp to the same + value as original eRuby file. For example, if you restore eRuby files + from backup, Erubis::Eruby#load_file() can detect it and generate + cache file again. + + ## generates cache file (A.rhtml.cache). + eruby = Erubis::Eruby.load_file('A.rhtml') + p File.mtime('A.rhtml') == File.mtime('A.rhtml.cache') #=> true + + + +- release: 2.6.6 + date: 2010-06-27 + bugfixes: + + - | + Fixed a bug around InterporationEnhancer and FastEruby to escape back-quote. (thanks to Andrew R Jackson) + + +- release: 2.6.5 + date: 2009-07-20 + bugfixes: + + - | + Fixed bug around '-z' option. + + +- release: 2.6.4 + date: 2009-02-18 + enhancements: + + - | + Rails 2.2 and 2.3 support. + + + +- release: 2.6.3 + date: 2009-02-07 + bugfixes: + + - Enhancer name was not displayed in Ruby 1.9.1 when it was missing. + + - Command option argument name was not displayed correctly as a part of error message. + + - MethoNotFound error was raised when invalid option was specified. + + +- release: 2.6.2 + date: 2008-06-12 + enhancements: + + - | + Ruby 1.9 support. + + bugfixes: + + - | + Fixed installation problem on Windows (Thanks to Tim Morgan and Allen). + + +- release: 2.6.1 + date: 2008-06-06 + enhancements: + + - | + Rails 2.1 support. (special thanks José Valim) + + + +- release: 2.6.0 + date: 2008-05-05 + enhancements: + + - | + Improved support of Ruby on Rails 2.0.2. + New class ActionView::TemplateHandlers::Erubis is defined and + registered as default handler of *.html.erb and *.rhtml. + + - | + '<%% %>' and '<%%= %>' are converted into '<% %>' and '<%= %>' respectively. + This is for compatibility with ERB. + + ex1.rhtml: +
    + <%% for item in @list %> +
  • <%%= item %>
  • + <%% end %> +
+ + result: + $ erubis ex1.rhtml +
    + <% for item in @list %> +
  • <%= item %>
  • + <% end %> +
+ + - | + '<%= -%>' removes tail spaces and newlines. + This is for compatibiliy with ERB when trim mode is '-'. + '<%= =%>' also removes tail spaces and newlines, and this is + Erubis-original enhancement (cooler than '<%= -%>', isn't it?). + + ex2.rhtml: +
+ <%= @var -%> # or <%= @var =%> +
+ + result (version 2.6.0): + $ erubis -c '{var: "AAA\n"}' ex2.rhtml +
+ AAA +
+ + result (version 2.5.0): + $ erubis -c '{var: "AAA\n"}' ex2.rhtml +
+ AAA + +
+ + - | + Erubis::Eruby.load_file() now allows you to change cache filename. + + ex. + eruby = Erubis::Eruby.load_file("ex3.rhtml", + :cachename=>'ex3.rhtml.cache') + + +- release: 2.5.0 + date: 2008-01-30 + enhancements: + + - | + Ruby on Rails 2.0 support. + If you are using preprocessing, notice that _?('foo.id') will be NG + because it contains period ('.') character. + + -------------------- + + [%= link_to 'Edit', edit_user_path(_?('@user.id')) %] + [%= link_to 'Show', @user %] + [%= link_to 'Delete', @user, :confirm=>'OK?', :method=>:delete %] + + + <%= user_id = @user.id %> + [%= link_to 'Edit', edit_user_path(_?('user_id')) %] + [%= link_to 'Show', :action=>'show', :id=>_?('user_id') %] + [%= link_to 'Delete', {:action=>'destroy', :id=>_?('user_id')}, + {:confirm=>'OK?', :method=>:delete} %] + -------------------- + + - | + (experimental) + Rails form helper methods for preprocessing are added. + These helper methos are available with preprocessing. + + ex. _form.rhtml + -------------------- + Name: <%= text_field :user, :name %> + Name: [%= pp_text_field :user, :name %] + -------------------- + + preprocessed: + -------------------- + Name: <%= text_field :user, :name %> + Name: + -------------------- + + Ruby code: + -------------------- + _buf << ' + Name: '; _buf << ( text_field :stock, :name ).to_s; _buf << ' + Name: + '; + -------------------- + + This shows that text_filed() is called every time when rendering, + but pp_text_filed() is called only once when loading template, + so pp_text_field() with prepocessing is much faster than text_field(). + + See User's guide for details. + http://www.kuwata-lab.com/erubis/users-guide.05.html#rails-formhelpers + +# +- release: 2.4.1 + date: 2007-09-25 + enhancements: + + - | + Add new section 'evaluate(context) v.s. result(binding)' to user's guide. + This section describes why Erubis::Eruby#evaluate(context) is recommended + rather than Erubis::Eruby#result(binding). + User's Guide > Other Topics > evaluate(context) v.s. result(binding) + http://www.kuwata-lab.com/erubis/users-guide.06.html#topics-context-vs-binding + + - | + Add new command-line property '--docwrite={true|false}' to + Erubis::Ejavascript. + If this property is true then 'document.write(_buf.join(""));' is used + as postamble and if it is false then '_buf.join("")' is used. + Default is true for compatibility reason but it will be false in the + future release. + (This feature was proposed by D.Dribin. Thank you.) + + bugfix: + + - | + When using Erubis::Eruby#evaluate(), changing local variables in + templates have affected to variables accessible with TOPLEVEL_BINDING. + It means that if you change variables in templates, it is possible to + change variables in main program. + This was a bug and is now fixed not to affect to variables in main + program. + + ex. template.rhtml + -------------------- + <% for x in @items %> + item = <%= x %> + <% end %> + -------------------- + + ex. main-program.rb + -------------------- + require 'erubis' + x = 10 + items = ['foo', 'bar', 'baz'] + eruby = Erubis::Eruby.new(File.read('template.rhtml')) + s = eruby.evaluate(:items=>items) + print s + $stderr.puts "*** debug: x=#{x.inspect}" #=> x="baz" (2.4.0) + #=> x=10 (2.4.1) + -------------------- + + - | + PercentLineEnhancer was very slow. Now performance problem is solved. + + +# +- release: 2.4.0 + date: 2007-07-19 + enhancements: + + - | + Preprocessing is supported by Ruby on Rails helper. + Preprocessing makes Ruby on Rails application about 20-40 percent faster. + + For example, + + [%= link_to 'Show', :action=>'show', :id=>_?('@user.id') %] + + is evaluate by preprocessor and expanded into the following + when template file is loaded. + + Show + + It means that link_to() is not called when template is rendered + and rendering speed will be much faster in the result. + + See User's Guide for details. + + - | + Erubis::Eruby#evaluate() (or Erubis::RubyEvaluator#evaluate()) now + creates Proc object from @src and eval it. + + def evaluate(context=Context.new) + context = Context.new(context) if context.is_a?(Hash) + @_proc ||= eval("proc { #{@src} }", TOPLEVEL_BINDING, @filename || '(erubis)') + return context.instance_eval(&@_proc) + end + + This makes evaluate() much faster when eruby object is reused. + + - | + Erubis::Eruby#def_method() is supported. + This method defines ruby code as instance method or singleton metod. + + require 'erubis' + s = "hello <%= name %>" + eruby = Erubis::Eruby.new(s) + filename = 'hello.rhtml' + + ## define instance method to Dummy class (or module) + class Dummy; end + eruby.def_method(Dummy, 'render(name)', filename) # filename is optional + p Dummy.new.render('world') #=> "hello world" + + ## define singleton method to an object + obj = Object.new + eruby.def_method(obj, 'render(name)', filename) # filename is optional + p obj.render('world') #=> "hello world" + + This is equivarent to ERB#def_method(). + + - | + Erubis::XmlHelper.url_escape() and u() which is alias of url_escape() + are added. + This is equivarent to ERB#Util.url_escape(). + + + bugfix: + - Help message was not shown when '-h' is specified. Fixed. + - 'def method()' was not availabe in template file. Fixed. + + +# +- release: 2.3.1 + date: 2007-05-26 + bugfix: + - A serious bug in 'helpers/rails_helper.rb' is fixed. + You must be update if you are using Erubis with Ruby on Rails. + + +# +- release: 2.3.0 + date: 2007-05-23 + enhancements: + - | + New class 'Erubis::FastEruby' is added. + It is a subclass of Erubis::Eruby and includes InterpolationEnhancer. + Erubis::FastEruby is compatible with and faster than Erubis::Eruby. + + - | + New enhancer 'InterpolationEnhancer' is added. + This enhancer uses expression interpolation to eliminate method call + of String#<<. In the result, this enhancer makes Eruby a little faster. + + -------------------- + ## Assume that input is '<%=name%>'. + ## Eruby convert input into the following code. String#<< is called 5 times. + _buf << ''; _buf << (name).to_s; _buf << ''; + + ## When InterpolationEnhancer is used, String#<< is called only once. + _buf << %Q`#{name}`; + -------------------- + + - | + New enhancer 'ErboutEnhancer' is added. + ErboutEnhancer set '_erbout' as well as '_buf' to be compatible with ERB. + + ex. + ==================== + $ cat ex.rhtml +

Hello

+ $ erubis -x ex.rhtml + _buf = ''; _buf << '

Hello

+ '; + _buf.to_s + $ erubis -xE Erbout ex.rhtml + _erbout = _buf = ''; _buf << '

Hello

+ '; + _buf.to_s + ==================== + + - | + [experimental] + New enhancer 'DeleteIndentEnhancer' is added. + This enhancer deletes indentation of HTML file. + + ex. + ==================== + $ cat ex.rhtml +
+
    + <% for item in ['AAA', 'BBB', 'CCC'] %> +
  • <%= item %>
  • + <% end %> +
+
+ $ erubis ex.rhtml +
+
    +
  • AAA
  • +
  • BBB
  • +
  • CCC
  • +
+
+ $ erubis -E DeleteIndent ex.rhtml +
+
    +
  • AAA
  • +
  • BBB
  • +
  • CCC
  • +
+
+ ==================== + + - | + Mod_ruby is supported (very thanks to Andrew R Jackson!). + See users-guide and 'contrib/erubis-run.rb' for details. + + - | + New command-line option '-X', '-N', '-U', and '-C' are added. + These are intended to be a replacement of 'notext' command. + '-X' shows only ruby statements and expressions. + '-N' adds line numbers. + '-U' compress empty lines into a line. + '-C' removes empty lines. + + + changes: + + - | + 'helpers/rails_helper.rb' is changed to use ErboutEnhancer. + The following is an examle to use Erubis with Ruby on Rails. + + File 'config/environment.rb': + ---------------------------------------- + require 'erubis/helpers/rails_helper' + #Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby # or Erubis::FastEruby + #Erubis::Helpers::RailsHelper.init_properties = {} + #Erubis::Helpers::RailsHelper.show_src = false # set true for debugging + ---------------------------------------- + + - | + Command 'notext' has been removed. Use '-X', '-N', '-U', and '-C' + instead. + + - | + Tab characters in YAML file are expaneded automatically. + If you want not to expand tab characters, add command-line optio '-T'. + + - | + Benchmark scripts (benchmark/bench.*) are rewrited. + + - | + Users-guide (doc/users-guide.html) is updated. + + + +# +- release: 2.2.0 + date: 2007-02-11 + enhancements: + - | + Performance tuned up. Release 2.2.0 works about 8 percent faster + than 2.1.0. + As a result, Erubis works more than 10 percent faster than eruby. + (eruby is the extension module of eRuby written in C.) + + - | + Support of Ruby on Rails improved. + If you want to use Erubis with Ruby on Rails, add the following code + into your 'config/environment.rb' and restart web server. + This will set Erubis as eRuby compiler in Ruby on Rails instead of ERB. + + -------------------- + require 'erubis/helpers/rails_helper' + #Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby + #Erubis::Helpers::RailsHelper.init_properties = {} + #Erubis::Helpers::RailsHelper.show_src = true + -------------------- + + Methods 'capture()' and 'content_for()' of ActionView::Helpers::CaptureHelper + are available. Methd ActionView::Helpers::TextHelper#concat() is also available. + + If Erubis::Helpers::RailsHelper.show_src is ture, Erubis prints converted + Ruby code into log file (such as 'log/development.log'). + + - | + Erubis::Engine.load_file(filename) creates cache file (filename + + '.cache') automatically if cache file is old or not exist. + Caching makes Erubis about 40-50 percent faster. + + ex. + -------------------- + require 'erubis' + eruby = Erubis::Eruby.load_file('example.rhtml') + ## cache file 'example.rhtml.cache' is created automatically + -------------------- + + - | + Command-line option '-f datafile' can take Ruby script ('*.rb') + as well as YAML file ('*.yaml' or '*.yml'). + + ex. + ==================== + $ cat context.rb + @title = 'Example' + @list = %w[AAA BBB CCC] + $ cat example.rhtml +

<%= @title %>

+
    + <% for item in @list %> +
  • <%= item %>
  • + <% end %> +
+ $ erubis -f context.rb example.rhtml +

Example

+
    +
  • AAA
  • +
  • BBB
  • +
  • CCC
  • +
+ ==================== + + - | + New command-line option '-c context' support. It takes context string + in YAML inline style or Ruby code style. + + ex. YAML inline style + ==================== + $ erubis -c '{title: Example, list: [AAA, BBB, CCC]}' example.rhtml + ==================== + + ex. Ruby style + ==================== + $ erubis -c '@title="Example"; @list=%w[AAA BBB CCC]' example.rhtml + ==================== + + - | + New command-line option '-z' (syntax checking) support. It is similar + to 'erubis -x file.rhtml | ruby -wc', but it can take several filenames. + + ex. + ==================== + $ erubis -z app/views/*/*.rhtml + Syntax OK + ==================== + + - | + New constant Erubis::VERSION added. + + + changes: + - | + Class Erubis::Eruby changed to include Erubis::StringBufferEnhancer + instead of Erubis::ArrayBufferEnhancer. + This is for Ruby on Rails support. + + ex. + ==================== + $ cat example.rhtml +
    + <% for item in @list %> +
  • <%= item %>
  • + <% end %> +
+ $ erubis -x example.rhtml + _buf = ''; _buf << '
    + '; for item in @list + _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • + '; end + _buf << '
+ '; + _buf.to_s + ==================== + + - | + Erubis::StringBufferEnhancer#add_postamble() prints "_buf.to_s" + instead of "_buf". + This is useful for 'erubis -x file.rhtml | ruby -wc'. + + - | + Command-line option '-T' is removed. Use '--trim=false' instead. + + - | + License is changed to MIT License. + + - | + Embedded pattern '<%- -%>' can be handled. + + +# +- release: 2.1.0 + date: 2006-09-23 + enhancements: + - | + Ruby on Rails support. Add the following code to + your 'app/controllers/application.rb' and restart web server. + + -------------------- + require 'erubis/helper/rails' + suffix = 'erubis' + ActionView::Base.register_template_handler(suffix, Erubis::Helper::RailsTemplate) + #Erubis::Helper::RailsTemplate.engine_class = Erubis::EscapedEruby ## or Erubis::PI::Eruby + #Erubis::Helper::RailsTemplate.default_properties = { :escape=>true, :escapefunc=>'h' } + -------------------- + + And rename your view template as 'xxx.erubis'. + If you got the "(eval):10:in `render': no block given" error, + use '@content_for_layout' instead 'yield' in your layout template. + + - | + Another eRuby engine (PIEngine) support. This engine doesn't + break HTML design because it uses Processing Instructions (PI) + '' as embedded pattern instead of '<% .. %>'. + + example.rhtml + -------------------- + + + + + + + +
@!{item}@
+ -------------------- + + compile: + ==================== + $ erubis -x --pi example.rhtml + _buf = []; _buf << ' + '; @list.each_with_index do |item, i| + klass = i % 2 == 0 ? 'odd' : 'even' + _buf << ' + + + '; end + _buf << '
'; _buf << (item).to_s; _buf << '
+ '; + _buf.join + ==================== + + - | + Add new command 'notext' which remove text part from eRuby + script and leaves only Ruby code. + This is very useful for debug of eRuby script. + + example2.rhtml + -------------------- + + + + <% @list.each_with_index do |item, i| %> + <% klass = i % 2 == 0 ? 'odd' : 'even' %> + + + + <% end %> +
<%== item %>
+ + + -------------------- + + command line example: + ==================== + $ notext example2.rhtml + _buf = []; + + + @list.each_with_index do |item, i| ; + klass = i % 2 == 0 ? 'odd' : 'even' ; + _buf << ( klass ).to_s; + _buf << Erubis::XmlHelper.escape_xml( item ); + + end ; + + + + _buf.join + $ notext -nc example2.rhtml + 1: _buf = []; + 4: @list.each_with_index do |item, i| ; + 5: klass = i % 2 == 0 ? 'odd' : 'even' ; + 6: _buf << ( klass ).to_s; + 7: _buf << Erubis::XmlHelper.escape_xml( item ); + 9: end ; + 13: _buf.join + ==================== + + - | + Add new enhance 'NoCode' which removes ruby code from + eRuby script and leaves only HTML text part. + It is very useful to validate HTML of eRuby script. + + command-line example: + ==================== + $ erubis -x -E NoCode example2.rhtml + + + + + + + + + +
+ + + ==================== + + changes: + - License is changed to LGPL. + - Command-line property '--escape=name' is renamed to + '--escapefunc=name'. + - When command-line option '-l perl' is specified, function + 'encode_entities()' is used ad escaping function which is + available wth HTML::Entities module. + + bugfix: + - There is a certain pattern which makes Engine#convert() + too slow. Now Engne#convert() is fixed not to be slown. + - Command name is now displayed when '-h' is specified. + + +# +- release: 2.0.1 + date: 2006-06-21 + bugfix: + - some minor bugs are fixed + + +# +- release: 2.0.0 + date: 2006-05-20 + changes: + - module 'PrintEnhancer' is renamed to 'PrintEnabledEnahncer' + - module 'FastEnhancer' and class 'FastEruby' is obsolete because they are integrated into Eruby class + - Eruby#evaluate() calls instance_eval() instead of eval() + - XmlEruby.escape_xml() is moved to XmlHelper.escape_xml() + enhancements: + - multi programming language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) + - class Eruby runs very fast because FastEnhancer module is integrated into Eruby by default + - TinyEruby class (tiny.rb) is added + - module ArrayBufferEnhancer added + - module ArrayEnhancer added + - module BiPatternEnhancer added + - module EscapeEnhancer added + - module HeaderFooterEnhancer added + - module NoTextEnhancer added + - module PercentLineEnhancer added + - module PrintEnabledEnhancer added + - module PrintOutEnhancer added + - module SimplifyEnhancer added + - module StringBufferEnhancer added + - module StringIOEnhancer added + - command-line option '-b' (body only) added + - command-line option '-e' (escape) added + - command-line option '-l' (lang) added + - command-line option '-E' (enhancer) added + - command-line option '-I' (require path) added + - command-line option '-K' (kanji code) added + - command-line option '-S' (string to symbol) added + - command-line option '-B' (call result(binding())) added + + +# +- release: 1.1.0 + date: 2006-03-05 + enhancements: + - '<%# ... %>' is supported + - PrintEnhancer, PrintEruby, and PrintXmlEruby added + +- release: 1.0.1 + date: 2006-02-01 + bugfixes: + - bin/erubis is available with RubyGems + + +# +- release: 1.0.0 + date: 2006-02-01 + bugfixes: + - first release + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/MIT-LICENSE b/vendor/ruby/1.9.1/gems/erubis-2.7.0/MIT-LICENSE new file mode 100644 index 0000000..c0e8bda --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/MIT-LICENSE @@ -0,0 +1,20 @@ +copyright(c) 2006-2011 kuwata-lab.com all rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/README.txt b/vendor/ruby/1.9.1/gems/erubis-2.7.0/README.txt new file mode 100644 index 0000000..2197948 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/README.txt @@ -0,0 +1,102 @@ += README + +release:: 2.7.0 +copyright:: copyright(c) 2006-2011 kuwata-lab.com all rights reserved. + + + +== About Erubis + +Erubis is an implementation of eRuby. It has the following features. +* Very fast, almost three times faster than ERB and even 10% faster than eruby +* Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) +* Auto escaping support +* Auto trimming spaces around '<% %>' +* Embedded pattern changeable (default '<% %>') +* Enable to handle Processing Instructions (PI) as embedded pattern (ex. '') +* Context object available and easy to combine eRuby template with YAML datafile +* Print statement available +* Easy to extend and customize in subclass +* Ruby on Rails support + +Erubis is implemented in pure Ruby. It requires Ruby 1.8 or higher. +Erubis now supports Ruby 1.9. + +See doc/users-guide.html for details. + + + +== Installation + +* If you have installed RubyGems, just type gem install erubis. + + $ sudo gem install erubis + +* Else install abstract[http://rubyforge.org/projects/abstract/] at first, + and download erubis_X.X.X.tar.bz2 and install it by setup.rb. + + $ tar xjf abstract_X.X.X.tar.bz2 + $ cd abstract_X.X.X/ + $ sudo ruby setup.rb + $ cd .. + $ tar xjf erubis_X.X.X.tar.bz2 + $ cd erubis_X.X.X/ + $ sudo ruby setup.rb + +* (Optional) It is able to merge 'lib/**/*.rb' into 'bin/erubis' by + 'contrib/inline-require' script. + + $ tar xjf erubis_X.X.X.tar.bz2 + $ cd erubis_X.X.X/ + $ cp /tmp/abstract_X.X.X/lib/abstract.rb lib + $ unset RUBYLIB + $ contrib/inline-require -I lib bin/erubis > contrib/erubis + + + +== Ruby on Rails Support + +Erubis supports Ruby on Rails. +All you have to do is to add the following code into your 'config/environment.rb' +and restart web server. + + require 'erubis/helpers/rails_helper' + #Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby + #Erubis::Helpers::RailsHelper.init_properties = {} + #Erubis::Helpers::RailsHelper.show_src = nil + +If Erubis::Helpers::RailsHelper.show_src is ture, Erubis prints converted Ruby code +into log file ('log/development.log' or so). It is useful for debug. + + + +== Exploring Guide + +If you are exploring Eruby, see the following class at first. +* Erubis::TinyEruby (erubis/tiny.rb) -- + the most simple eRuby implementation. +* Erubis::Engine (erubis/engine.rb) -- + base class of Eruby, Ephp, Ejava, and so on. +* Erubis::Eruby (erubis/engine/eruby.rb) -- + engine class for eRuby. +* Erubis::Converter (erubis/converter.rb) -- + convert eRuby script into Ruby code. + + + +== Benchmark + +'benchmark/erubybenchmark.rb' is a benchmark script of Erubis. +Try 'ruby erubybenchmark.rb' in benchmark directory. + + + +== License + +MIT License + + + +== Author + +makoto kuwata diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/Makefile b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/Makefile new file mode 100644 index 0000000..fa740fe --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/Makefile @@ -0,0 +1,6 @@ + +bench: + ruby bench.rb -n 10000 + +clean: + rm -rf bench_*.rhtml* diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/bench.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/bench.rb new file mode 100644 index 0000000..85ceb16 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/bench.rb @@ -0,0 +1,313 @@ +#!/usr/bin/env ruby + +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'erb' +require 'erubis' +require 'erubis/tiny' +require 'erubis/engine/enhanced' +require 'yaml' +require 'cgi' +include ERB::Util + +begin + require 'eruby' +rescue LoadError + ERuby = nil +end + +def File.write(filename, content) + File.open(filename, 'w') { |f| f.write(content) } +end + + +## change benchmark library to use $stderr instead of $stdout +require 'benchmark' +module Benchmark + class Report + def print(*args) + $stderr.print(*args) + end + end + module_function + def print(*args) + $stderr.print(*args) + end +end + + +class BenchmarkApplication + + TARGETS = %w[eruby + ERB ERB(cached) + Erubis::Eruby Erubis::Eruby(cached) + Erubis::FastEruby Erubis::FastEruby(cached) + Erubis::TinyEruby + Erubis::ArrayBufferEruby + Erubis::PrintOutEruby + Erubis::StdoutEruby + ] + + def initialize(ntimes, context, targets=nil, params={}) + @ntimes = ntimes + @context = context + @targets = targets && !targets.empty? ? targets : TARGETS.dup + @testmode = params[:testmode] || 'execute' + @erubyfile = params[:erubyfile] || 'erubybench.rhtml' + @printout = params[:printout] || false + end + + attr_accessor :ntimes, :targets + attr_accessor :testmode, :erubyfile, :contextfile, :printout + + def context2code(context, varname='context') + s = '' + context.each { |k, | s << "#{k} = #{varname}[#{k.inspect}]; " } + return s + end + + def perform_benchmark + width = 30 + $stderr.puts "*** ntimes=#{@ntimes}, testmode=#{@testmode}" + Benchmark.bm(width) do |job| + for target in @targets do + method = "#{@testmode}_#{target.gsub(/::|-|\(/, '_').gsub(/\)/, '').downcase}" + #$stderr.puts "*** debug: method=#{method.inspect}" + next unless self.respond_to?(method) + filename = "bench_#{(target =~ /^(\w+)/) && $1.downcase}.rhtml" + title = target + output = nil + job.report(title) do + output = self.__send__(method, filename, @context) + end + File.write("output.#{target.gsub(/[^\w]/,'')}", output) if @printout && output && !output.empty? + end + end + end + + ## + + def execute_eruby(filename, context) + return unless ERuby + #eval context2code(context) + list = context['list'] + @ntimes.times do + ERuby.import(filename) + end + return nil + end + + def execute_erb(filename, context) + #eval context2code(context) + list = context['list'] + output = nil + @ntimes.times do + eruby = ERB.new(File.read(filename)) + output = eruby.result(binding()) + print output + end + return output + end + + def execute_erb_cached(filename, context) + #eval context2code(context) + list = context['list'] + output = nil + cachefile = filename + '.cache' + File.unlink(cachefile) if test(?f, cachefile) + @ntimes.times do + if !test(?f, cachefile) || File.mtime(filename) > File.mtime(cachefile) + eruby = ERB.new(File.read(filename)) + File.write(cachefile, eruby.src) + else + eruby = ERB.new('') + #eruby.src = File.read(cachefile) + eruby.instance_variable_set("@src", File.read(cachefile)) + end + output = eruby.result(binding()) + print output + end + return output + end + + ## no cached + for klass in %w[Eruby FastEruby TinyEruby ArrayBufferEruby PrintOutEruby StdoutEruby] do + s = <<-END + def execute_erubis_#{klass.downcase}(filename, context) + #eval context2code(context) + list = context['list'] + output = nil + @ntimes.times do + eruby = Erubis::#{klass}.new(File.read(filename)) + output = eruby.result(binding()) + print output + end + return output + end + END + eval s + end + + ## cached + for klass in %w[Eruby FastEruby] do + s = <<-END + def execute_erubis_#{klass.downcase}_cached(filename, context) + #eval context2code(context) + list = context['list'] + cachefile = filename + '.cache' + File.unlink(cachefile) if test(?f, cachefile) + output = nil + @ntimes.times do + eruby = Erubis::#{klass}.load_file(filename) + output = eruby.result(binding()) + print output + end + savefile = cachefile.sub(/\\.cache$/, '.#{klass.downcase}.cache') + File.rename(cachefile, savefile) + return output + end + END + eval s + end + + ## + + def convert_eruby(filename, context) + return unless ERuby + #eval context2code(context) + list = context['list'] + output = nil + @ntimes.times do + output = ERuby::Compiler.new.compile_string(File.read(filename)) + end + return output + end + + def convert_erb(filename, context) + #eval context2code(context) + list = context['list'] + output = nil + @ntimes.times do + eruby = ERB.new(File.read(filename)) + output = eruby.src + end + return output + end + + for klass in %w[Eruby FastEruby TinyEruby] + s = <<-END + def convert_erubis_#{klass.downcase}(filename, context) + #eval context2code(context) + list = context['list'] + output = nil + @ntimes.times do + eruby = Erubis::#{klass}.new(File.read(filename)) + output = eruby.src + end + return output + end + END + eval s + end + +end + + +require 'optparse' + +class MainApplication + + def parse_argv(argv=ARGV) + optparser = OptionParser.new + options = {} + ['-h', '-n N', '-t erubyfile', '-f contextfile', '-A', '-e', + '-x exclude', '-m testmode', '-X', '-p', '-D'].each do |opt| + optparser.on(opt) { |val| options[opt[1].chr] = val } + end + begin + targets = optparser.parse!(argv) + rescue => ex + $stderr.puts "#{@script}: #{ex.to_s}" + exit(1) + end + return options, targets + end + + def execute + @script = File.basename($0) + ntimes = 1000 + targets = BenchmarkApplication::TARGETS.dup + testmode = 'execute' + contextfile = 'bench_context.yaml' + # + options, args = parse_argv(ARGV) + ntimes = options['n'].to_i if options['n'] + targets = args if args && !args.empty? + targets = targets - options['x'].split(/,/) if options['x'] + testmode = options['m'] if options['m'] + contextfile = options['f'] if options['f'] + erubyfile = options['t'] if options['t'] + # + if options['h'] + $stderr.puts "Usage: ruby #{@script} [..options..] [..targets..]" + $stderr.puts " -h : help" + $stderr.puts " -n N : loop N times" + $stderr.puts " -f datafile : context data filename (*.yaml)" + $stderr.puts " -x exclude : exclude target name" + $stdout.puts " -m testmode : 'execute' or 'convert' (default 'execute')" + $stderr.puts " -p : print output to file (filename: 'output.TARGETNAME')" + return + end + # + #if ! options['t'] + for item in %w[eruby erb erubis] + fname = "bench_#{item}.rhtml" + header = File.read("templates/_header.html") + #body = File.read("templates/#{erubyfile}") + body = File.read("templates/#{fname}") + footer = File.read("templates/_footer.html") + content = header + body + footer + File.write(fname, content) + end + # + if options['e'] # escape + tuples = [ + [ 'bench_eruby.rhtml', '<%= CGI.escapeHTML((\1).to_s) %>' ], + [ 'bench_erb.rhtml', '<%=h \1 %>' ], + [ 'bench_erubis.rhtml', '<%== \1 %>' ], + ] + for fname, replace in tuples + content = File.read(fname).gsub(/<%= ?(.*?) ?%>/, replace) + File.write(fname, content) + end + targets.delete('Erubis::TinyEruby') ## because TinyEruby doesn't support '<%== =>' + end + # + context = YAML.load_file(contextfile) + # + params = { + :printout=>options['p'], + :testmode=>testmode, + } + app = BenchmarkApplication.new(ntimes, context, targets, params) + app.perform_benchmark() + end + +end + + +if __FILE__ == $0 + + ## open /dev/null + $stdout = File.open('/dev/null', 'w') + at_exit do + $stdout.close() + end + + ## start benchmark + MainApplication.new().execute() + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/bench_context.yaml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/bench_context.yaml new file mode 100644 index 0000000..e0ab4e8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/bench_context.yaml @@ -0,0 +1,141 @@ +list: + - name: Adobe Systems + name2: Adobe Systems Inc. + url: http://www.adobe.com + symbol: ADBE + price: 39.26 + change: 0.13 + ratio: 0.33 + - name: Advanced Micro Devices + name2: Advanced Micro Devices Inc. + url: http://www.amd.com + symbol: AMD + price: 16.22 + change: 0.17 + ratio: 1.06 + - name: Amazon.com + name2: Amazon.com Inc + url: http://www.amazon.com + symbol: AMZN + price: 36.85 + change: -0.23 + ratio: -0.62 + - name: Apple + name2: Apple Inc. + url: http://www.apple.com + symbol: AAPL + price: 85.38 + change: -0.87 + ratio: -1.01 + - name: BEA Systems + name2: BEA Systems Inc. + url: http://www.bea.com + symbol: BEAS + price: 12.46 + change: 0.09 + ratio: 0.73 + - name: CA + name2: CA, Inc. + url: http://www.ca.com + symbol: CA + price: 24.66 + change: 0.38 + ratio: 1.57 + - name: Cisco Systems + name2: Cisco Systems Inc. + url: http://www.cisco.com + symbol: CSCO + price: 26.35 + change: 0.13 + ratio: 0.5 + - name: Dell + name2: Dell Corp. + url: http://www.dell.com/ + symbol: DELL + price: 23.73 + change: -0.42 + ratio: -1.74 + - name: eBay + name2: eBay Inc. + url: http://www.ebay.com + symbol: EBAY + price: 31.65 + change: -0.8 + ratio: -2.47 + - name: Google + name2: Google Inc. + url: http://www.google.com + symbol: GOOG + price: 495.84 + change: 7.75 + ratio: 1.59 + - name: Hewlett-Packard + name2: Hewlett-Packard Co. + url: http://www.hp.com + symbol: HPQ + price: 41.69 + change: -0.02 + ratio: -0.05 + - name: IBM + name2: International Business Machines Corp. + url: http://www.ibm.com + symbol: IBM + price: 97.45 + change: -0.06 + ratio: -0.06 + - name: Intel + name2: Intel Corp. + url: http://www.intel.com + symbol: INTC + price: 20.53 + change: -0.07 + ratio: -0.34 + - name: Juniper Networks + name2: Juniper Networks, Inc + url: http://www.juniper.net/ + symbol: JNPR + price: 18.96 + change: 0.5 + ratio: 2.71 + - name: Microsoft + name2: Microsoft Corp + url: http://www.microsoft.com + symbol: MSFT + price: 30.6 + change: 0.15 + ratio: 0.49 + - name: Oracle + name2: Oracle Corp. + url: http://www.oracle.com + symbol: ORCL + price: 17.15 + change: 0.17 + ratio: 1.0 + - name: SAP + name2: SAP AG + url: http://www.sap.com + symbol: SAP + price: 46.2 + change: -0.16 + ratio: -0.35 + - name: Seagate Technology + name2: Seagate Technology + url: http://www.seagate.com/ + symbol: STX + price: 27.35 + change: -0.36 + ratio: -1.3 + - name: Sun Microsystems + name2: Sun Microsystems Inc. + url: http://www.sun.com + symbol: SUNW + price: 6.33 + change: -0.01 + ratio: -0.16 + - name: Yahoo + name2: Yahoo! Inc. + url: http://www.yahoo.com + symbol: YHOO + price: 28.04 + change: -0.17 + ratio: -0.6 diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/_footer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/_footer.html new file mode 100644 index 0000000..3ae6d4d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/_footer.html @@ -0,0 +1,4 @@ + + + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/_header.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/_header.html new file mode 100644 index 0000000..cbab956 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/_header.html @@ -0,0 +1,52 @@ + + + + + Stock Prices + + + + + + + + + + + + +

Stock Prices

+ + + + + + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_erb.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_erb.rhtml new file mode 100644 index 0000000..3dde9d5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_erb.rhtml @@ -0,0 +1,29 @@ + +<% +n = 0 +for item in list + n += 1 + %> + + + + + +<% if item['change'] < 0.0 %> + + +<% else %> + + +<% end %> + +<% +end + %> + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_erubis.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_erubis.rhtml new file mode 100644 index 0000000..3dde9d5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_erubis.rhtml @@ -0,0 +1,29 @@ + +<% +n = 0 +for item in list + n += 1 + %> + + + + + +<% if item['change'] < 0.0 %> + + +<% else %> + + +<% end %> + +<% +end + %> + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_eruby.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_eruby.rhtml new file mode 100644 index 0000000..3dde9d5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/benchmark/templates/bench_eruby.rhtml @@ -0,0 +1,29 @@ + +<% +n = 0 +for item in list + n += 1 + %> + + + + + +<% if item['change'] < 0.0 %> + + +<% else %> + + +<% end %> + +<% +end + %> + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/bin/erubis b/vendor/ruby/1.9.1/gems/erubis-2.7.0/bin/erubis new file mode 100755 index 0000000..5a9fccf --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/bin/erubis @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby + +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'erubis/main' + +Erubis::Main.main(ARGV) diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis b/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis new file mode 100755 index 0000000..96385d3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis @@ -0,0 +1,3468 @@ +#!/usr/bin/env ruby + +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +#--begin of require 'erubis/main' +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'yaml' +#--begin of require 'erubis' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +## +## an implementation of eRuby +## +## ex. +## input = <<'END' +##
    +## <% for item in @list %> +##
  • <%= item %> +## <%== item %>
  • +## <% end %> +##
+## END +## list = ['', 'b&b', '"ccc"'] +## eruby = Erubis::Eruby.new(input) +## puts "--- code ---" +## puts eruby.src +## puts "--- result ---" +## context = Erubis::Context.new() # or new(:list=>list) +## context[:list] = list +## puts eruby.evaluate(context) +## +## result: +## --- source --- +## _buf = ''; _buf << '
    +## '; for item in @list +## _buf << '
  • '; _buf << ( item ).to_s; _buf << ' +## '; _buf << ' '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
  • +## '; end +## _buf << '
+## '; +## _buf.to_s +## --- result --- +##
    +##
  • +## <aaa>
  • +##
  • b&b +## b&b
  • +##
  • "ccc" +## "ccc"
  • +##
+## + + +module Erubis + VERSION = ('$Release: 2.7.0 $' =~ /([.\d]+)/) && $1 +end + +#--begin of require 'erubis/engine' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +#--begin of require 'erubis/generator' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--begin of require 'erubis/util' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +module Kernel + + ## + ## raise NotImplementedError + ## + def not_implemented #:doc: + backtrace = caller() + method_name = (backtrace.shift =~ /`(\w+)'$/) && $1 + mesg = "class #{self.class.name} must implement abstract method '#{method_name}()'." + #mesg = "#{self.class.name}##{method_name}() is not implemented." + err = NotImplementedError.new mesg + err.set_backtrace backtrace + raise err + end + private :not_implemented + +end +#--end of require 'erubis/util' + +module Erubis + + + ## + ## code generator, called by Converter module + ## + module Generator + + def self.supported_properties() # :nodoc: + return [ + [:escapefunc, nil, "escape function name"], + ] + end + + attr_accessor :escapefunc + + def init_generator(properties={}) + @escapefunc = properties[:escapefunc] + end + + + ## (abstract) escape text string + ## + ## ex. + ## def escape_text(text) + ## return text.dump + ## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'" + ## end + def escape_text(text) + not_implemented + end + + ## return escaped expression code (ex. 'h(...)' or 'htmlspecialchars(...)') + def escaped_expr(code) + code.strip! + return "#{@escapefunc}(#{code})" + end + + ## (abstract) add @preamble to src + def add_preamble(src) + not_implemented + end + + ## (abstract) add text string to src + def add_text(src, text) + not_implemented + end + + ## (abstract) add statement code to src + def add_stmt(src, code) + not_implemented + end + + ## (abstract) add expression literal code to src. this is called by add_expr(). + def add_expr_literal(src, code) + not_implemented + end + + ## (abstract) add escaped expression code to src. this is called by add_expr(). + def add_expr_escaped(src, code) + not_implemented + end + + ## (abstract) add expression code to src for debug. this is called by add_expr(). + def add_expr_debug(src, code) + not_implemented + end + + ## (abstract) add @postamble to src + def add_postamble(src) + not_implemented + end + + + end + + +end +#--end of require 'erubis/generator' +#--begin of require 'erubis/converter' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/util' + +module Erubis + + + ## + ## convert + ## + module Converter + + attr_accessor :preamble, :postamble, :escape + + def self.supported_properties # :nodoc: + return [ + [:preamble, nil, "preamble (no preamble when false)"], + [:postamble, nil, "postamble (no postamble when false)"], + [:escape, nil, "escape expression or not in default"], + ] + end + + def init_converter(properties={}) + @preamble = properties[:preamble] + @postamble = properties[:postamble] + @escape = properties[:escape] + end + + ## convert input string into target language + def convert(input) + codebuf = "" # or [] + @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble)) + convert_input(codebuf, input) + @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble)) + @_proc = nil # clear cached proc object + return codebuf # or codebuf.join() + end + + protected + + ## + ## detect spaces at beginning of line + ## + def detect_spaces_at_bol(text, is_bol) + lspace = nil + if text.empty? + lspace = "" if is_bol + elsif text[-1] == ?\n + lspace = "" + else + rindex = text.rindex(?\n) + if rindex + s = text[rindex+1..-1] + if s =~ /\A[ \t]*\z/ + lspace = s + #text = text[0..rindex] + text[rindex+1..-1] = '' + end + else + if is_bol && text =~ /\A[ \t]*\z/ + #lspace = text + #text = nil + lspace = text.dup + text[0..-1] = '' + end + end + end + return lspace + end + + ## + ## (abstract) convert input to code + ## + def convert_input(codebuf, input) + not_implemented + end + + end + + + module Basic + end + + + ## + ## basic converter which supports '<% ... %>' notation. + ## + module Basic::Converter + include Erubis::Converter + + def self.supported_properties # :nodoc: + return [ + [:pattern, '<% %>', "embed pattern"], + [:trim, true, "trim spaces around <% ... %>"], + ] + end + + attr_accessor :pattern, :trim + + def init_converter(properties={}) + super(properties) + @pattern = properties[:pattern] + @trim = properties[:trim] != false + end + + protected + + ## return regexp of pattern to parse eRuby script + def pattern_regexp(pattern) + @prefix, @postfix = pattern.split() # '<% %>' => '<%', '%>' + #return /(.*?)(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m + #return /(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m + return /#{@prefix}(=+|-|\#|%)?(.*?)([-=])?#{@postfix}([ \t]*\r?\n)?/m + end + module_function :pattern_regexp + + #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + #DEFAULT_REGEXP = /<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + DEFAULT_REGEXP = pattern_regexp('<% %>') + + public + + def convert_input(src, input) + pat = @pattern + regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat) + pos = 0 + is_bol = true # is beginning of line + input.scan(regexp) do |indicator, code, tailch, rspace| + match = Regexp.last_match() + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + ch = indicator ? indicator[0] : nil + lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol) + is_bol = rspace ? true : false + add_text(src, text) if text && !text.empty? + ## * when '<%= %>', do nothing + ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>' + if ch == ?= # <%= %> + rspace = nil if tailch && !tailch.empty? + add_text(src, lspace) if lspace + add_expr(src, code, indicator) + add_text(src, rspace) if rspace + elsif ch == ?\# # <%# %> + n = code.count("\n") + (rspace ? 1 : 0) + if @trim && lspace && rspace + add_stmt(src, "\n" * n) + else + add_text(src, lspace) if lspace + add_stmt(src, "\n" * n) + add_text(src, rspace) if rspace + end + elsif ch == ?% # <%% %> + s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}" + add_text(src, s) + else # <% %> + if @trim && lspace && rspace + add_stmt(src, "#{lspace}#{code}#{rspace}") + else + add_text(src, lspace) if lspace + add_stmt(src, code) + add_text(src, rspace) if rspace + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(src, rest) + end + + ## add expression code to src + def add_expr(src, code, indicator) + case indicator + when '=' + @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code) + when '==' + @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code) + when '===' + add_expr_debug(src, code) + end + end + + end + + + module PI + end + + ## + ## Processing Instructions (PI) converter for XML. + ## this class converts '' and '${...}' notation. + ## + module PI::Converter + include Erubis::Converter + + def self.desc # :nodoc: + "use processing instructions (PI) instead of '<% %>'" + end + + def self.supported_properties # :nodoc: + return [ + [:trim, true, "trim spaces around <% ... %>"], + [:pi, 'rb', "PI (Processing Instrunctions) name"], + [:embchar, '@', "char for embedded expression pattern('@{...}@')"], + [:pattern, '<% %>', "embed pattern"], + ] + end + + attr_accessor :pi, :prefix + + def init_converter(properties={}) + super(properties) + @trim = properties.fetch(:trim, true) + @pi = properties[:pi] if properties[:pi] + @embchar = properties[:embchar] || '@' + @pattern = properties[:pattern] + @pattern = '<% %>' if @pattern.nil? #|| @pattern == true + end + + def convert(input) + code = super(input) + return @header || @footer ? "#{@header}#{code}#{@footer}" : code + end + + protected + + def convert_input(codebuf, input) + unless @regexp + @pi ||= 'e' + ch = Regexp.escape(@embchar) + if @pattern + left, right = @pattern.split(' ') + @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m + else + @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m + end + end + # + is_bol = true + pos = 0 + input.scan(@regexp) do |pi_arg, stmt, rspace, + indicator1, expr1, indicator2, expr2| + match = Regexp.last_match + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil + is_bol = stmt && rspace ? true : false + add_text(codebuf, text) # unless text.empty? + # + if stmt + if @trim && lspace && rspace + add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg) + else + add_text(codebuf, lspace) if lspace + add_pi_stmt(codebuf, stmt, pi_arg) + add_text(codebuf, rspace) if rspace + end + else + add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2) + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(codebuf, rest) + end + + #-- + #def convert_input(codebuf, input) + # parse_stmts(codebuf, input) + # #parse_stmts2(codebuf, input) + #end + # + #def parse_stmts(codebuf, input) + # #regexp = pattern_regexp(@pattern) + # @pi ||= 'e' + # @stmt_pattern ||= /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m + # is_bol = true + # pos = 0 + # input.scan(@stmt_pattern) do |pi_arg, code, rspace| + # match = Regexp.last_match + # len = match.begin(0) - pos + # text = input[pos, len] + # pos = match.end(0) + # lspace = detect_spaces_at_bol(text, is_bol) + # is_bol = rspace ? true : false + # parse_exprs(codebuf, text) # unless text.empty? + # if @trim && lspace && rspace + # add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg) + # else + # add_text(codebuf, lspace) + # add_pi_stmt(codebuf, code, pi_arg) + # add_text(codebuf, rspace) + # end + # end + # rest = $' || input + # parse_exprs(codebuf, rest) + #end + # + #def parse_exprs(codebuf, input) + # unless @expr_pattern + # ch = Regexp.escape(@embchar) + # if @pattern + # left, right = @pattern.split(' ') + # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/ + # else + # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/ + # end + # end + # pos = 0 + # input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2| + # indicator = indicator1 || indicator2 + # code = code1 || code2 + # match = Regexp.last_match + # len = match.begin(0) - pos + # text = input[pos, len] + # pos = match.end(0) + # add_text(codebuf, text) # unless text.empty? + # add_pi_expr(codebuf, code, indicator) + # end + # rest = $' || input + # add_text(codebuf, rest) + #end + #++ + + def add_pi_stmt(codebuf, code, pi_arg) # :nodoc: + case pi_arg + when nil ; add_stmt(codebuf, code) + when 'header' ; @header = code + when 'footer' ; @footer = code + when 'comment'; add_stmt(codebuf, "\n" * code.count("\n")) + when 'value' ; add_expr_literal(codebuf, code) + else ; add_stmt(codebuf, code) + end + end + + def add_pi_expr(codebuf, code, indicator) # :nodoc: + case indicator + when nil, '', '==' # @{...}@ or <%== ... %> + @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code) + when '!', '=' # @!{...}@ or <%= ... %> + @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code) + when '!!', '===' # @!!{...}@ or <%=== ... %> + add_expr_debug(codebuf, code) + else + # ignore + end + end + + end + + +end +#--end of require 'erubis/converter' +#--begin of require 'erubis/evaluator' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--begin of require 'erubis/error' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +module Erubis + + + ## + ## base error class + ## + class ErubisError < StandardError + end + + + ## + ## raised when method or function is not supported + ## + class NotSupportedError < ErubisError + end + + +end +#--end of require 'erubis/error' +#--begin of require 'erubis/context' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +module Erubis + + + ## + ## context object for Engine#evaluate + ## + ## ex. + ## template = <<'END' + ## Hello <%= @user %>! + ## <% for item in @list %> + ## - <%= item %> + ## <% end %> + ## END + ## + ## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c']) + ## # or + ## # context = Erubis::Context.new + ## # context[:user] = 'World' + ## # context[:list] = ['a', 'b', 'c'] + ## + ## eruby = Erubis::Eruby.new(template) + ## print eruby.evaluate(context) + ## + class Context + include Enumerable + + def initialize(hash=nil) + hash.each do |name, value| + self[name] = value + end if hash + end + + def [](key) + return instance_variable_get("@#{key}") + end + + def []=(key, value) + return instance_variable_set("@#{key}", value) + end + + def keys + return instance_variables.collect { |name| name[1..-1] } + end + + def each + instance_variables.each do |name| + key = name[1..-1] + value = instance_variable_get(name) + yield(key, value) + end + end + + def to_hash + hash = {} + self.keys.each { |key| hash[key] = self[key] } + return hash + end + + def update(context_or_hash) + arg = context_or_hash + if arg.is_a?(Hash) + arg.each do |key, val| + self[key] = val + end + else + arg.instance_variables.each do |varname| + key = varname[1..-1] + val = arg.instance_variable_get(varname) + self[key] = val + end + end + end + + end + + +end +#--end of require 'erubis/context' + + +module Erubis + + EMPTY_BINDING = binding() + + + ## + ## evaluate code + ## + module Evaluator + + def self.supported_properties # :nodoc: + return [] + end + + attr_accessor :src, :filename + + def init_evaluator(properties) + @filename = properties[:filename] + end + + def result(*args) + raise NotSupportedError.new("evaluation of code except Ruby is not supported.") + end + + def evaluate(*args) + raise NotSupportedError.new("evaluation of code except Ruby is not supported.") + end + + end + + + ## + ## evaluator for Ruby + ## + module RubyEvaluator + include Evaluator + + def self.supported_properties # :nodoc: + list = Evaluator.supported_properties + return list + end + + ## eval(@src) with binding object + def result(_binding_or_hash=TOPLEVEL_BINDING) + _arg = _binding_or_hash + if _arg.is_a?(Hash) + _b = binding() + eval _arg.collect{|k,v| "#{k} = _arg[#{k.inspect}]; "}.join, _b + elsif _arg.is_a?(Binding) + _b = _arg + elsif _arg.nil? + _b = binding() + else + raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.") + end + return eval(@src, _b, (@filename || '(erubis')) + end + + ## invoke context.instance_eval(@src) + def evaluate(_context=Context.new) + _context = Context.new(_context) if _context.is_a?(Hash) + #return _context.instance_eval(@src, @filename || '(erubis)') + #@_proc ||= eval("proc { #{@src} }", Erubis::EMPTY_BINDING, @filename || '(erubis)') + @_proc ||= eval("proc { #{@src} }", binding(), @filename || '(erubis)') + return _context.instance_eval(&@_proc) + end + + ## if object is an Class or Module then define instance method to it, + ## else define singleton method to it. + def def_method(object, method_name, filename=nil) + m = object.is_a?(Module) ? :module_eval : :instance_eval + object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(erubis)') + end + + + end + + +end +#--end of require 'erubis/evaluator' +#--already included require 'erubis/context' + + +module Erubis + + + ## + ## (abstract) abstract engine class. + ## subclass must include evaluator and converter module. + ## + class Engine + #include Evaluator + #include Converter + #include Generator + + def initialize(input=nil, properties={}) + #@input = input + init_generator(properties) + init_converter(properties) + init_evaluator(properties) + @src = convert(input) if input + end + + + ## + ## convert input string and set it to @src + ## + def convert!(input) + @src = convert(input) + end + + + ## + ## load file, write cache file, and return engine object. + ## this method create code cache file automatically. + ## cachefile name can be specified with properties[:cachename], + ## or filname + 'cache' is used as default. + ## + def self.load_file(filename, properties={}) + cachename = properties[:cachename] || (filename + '.cache') + properties[:filename] = filename + timestamp = File.mtime(filename) + if test(?f, cachename) && timestamp == File.mtime(cachename) + engine = self.new(nil, properties) + engine.src = File.read(cachename) + else + input = File.open(filename, 'rb') {|f| f.read } + engine = self.new(input, properties) + tmpname = cachename + rand().to_s[1,8] + File.open(tmpname, 'wb') {|f| f.write(engine.src) } + File.rename(tmpname, cachename) + File.utime(timestamp, timestamp, cachename) + end + engine.src.untaint # ok? + return engine + end + + + ## + ## helper method to convert and evaluate input text with context object. + ## context may be Binding, Hash, or Object. + ## + def process(input, context=nil, filename=nil) + code = convert(input) + filename ||= '(erubis)' + if context.is_a?(Binding) + return eval(code, context, filename) + else + context = Context.new(context) if context.is_a?(Hash) + return context.instance_eval(code, filename) + end + end + + + ## + ## helper method evaluate Proc object with contect object. + ## context may be Binding, Hash, or Object. + ## + def process_proc(proc_obj, context=nil, filename=nil) + if context.is_a?(Binding) + filename ||= '(erubis)' + return eval(proc_obj, context, filename) + else + context = Context.new(context) if context.is_a?(Hash) + return context.instance_eval(&proc_obj) + end + end + + + end # end of class Engine + + + ## + ## (abstract) base engine class for Eruby, Eperl, Ejava, and so on. + ## subclass must include generator. + ## + class Basic::Engine < Engine + include Evaluator + include Basic::Converter + include Generator + end + + + class PI::Engine < Engine + include Evaluator + include PI::Converter + include Generator + end + + +end +#--end of require 'erubis/engine' +#require 'erubis/generator' +#require 'erubis/converter' +#require 'erubis/evaluator' +#require 'erubis/error' +#require 'erubis/context' +#requier 'erubis/util' +#--begin of require 'erubis/helper' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +module Erubis + + ## + ## helper for xml + ## + module XmlHelper + + module_function + + ESCAPE_TABLE = { + '&' => '&', + '<' => '<', + '>' => '>', + '"' => '"', + "'" => ''', + } + + def escape_xml(value) + value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/ + #value.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] } + end + + def escape_xml2(value) + return value.to_s.gsub(/\&/,'&').gsub(//,'>').gsub(/"/,'"') + end + + alias h escape_xml + alias html_escape escape_xml + + def url_encode(str) + return str.gsub(/[^-_.a-zA-Z0-9]+/) { |s| + s.unpack('C*').collect { |i| "%%%02X" % i }.join + } + end + + alias u url_encode + + end + + +end +#--end of require 'erubis/helper' +#--begin of require 'erubis/enhancer' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +module Erubis + + + ## + ## switch '<%= ... %>' to escaped and '<%== ... %>' to unescaped + ## + ## ex. + ## class XmlEruby < Eruby + ## include EscapeEnhancer + ## end + ## + ## this is language-indenedent. + ## + module EscapeEnhancer + + def self.desc # :nodoc: + "switch '<%= %>' to escaped and '<%== %>' to unescaped" + end + + #-- + #def self.included(klass) + # klass.class_eval <<-END + # alias _add_expr_literal add_expr_literal + # alias _add_expr_escaped add_expr_escaped + # alias add_expr_literal _add_expr_escaped + # alias add_expr_escaped _add_expr_literal + # END + #end + #++ + + def add_expr(src, code, indicator) + case indicator + when '=' + @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code) + when '==' + @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code) + when '===' + add_expr_debug(src, code) + end + end + + end + + + #-- + ## (obsolete) + #module FastEnhancer + #end + #++ + + + ## + ## use $stdout instead of string + ## + ## this is only for Eruby. + ## + module StdoutEnhancer + + def self.desc # :nodoc: + "use $stdout instead of array buffer or string buffer" + end + + def add_preamble(src) + src << "#{@bufvar} = $stdout;" + end + + def add_postamble(src) + src << "\n''\n" + end + + end + + + ## + ## use print statement instead of '_buf << ...' + ## + ## this is only for Eruby. + ## + module PrintOutEnhancer + + def self.desc # :nodoc: + "use print statement instead of '_buf << ...'" + end + + def add_preamble(src) + end + + def add_text(src, text) + src << " print '#{escape_text(text)}';" unless text.empty? + end + + def add_expr_literal(src, code) + src << " print((#{code}).to_s);" + end + + def add_expr_escaped(src, code) + src << " print #{escaped_expr(code)};" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + end + + end + + + ## + ## enable print function + ## + ## Notice: use Eruby#evaluate() and don't use Eruby#result() + ## to be enable print function. + ## + ## this is only for Eruby. + ## + module PrintEnabledEnhancer + + def self.desc # :nodoc: + "enable to use print function in '<% %>'" + end + + def add_preamble(src) + src << "@_buf = " + super + end + + def print(*args) + args.each do |arg| + @_buf << arg.to_s + end + end + + def evaluate(context=nil) + _src = @src + if context.is_a?(Hash) + context.each do |key, val| instance_variable_set("@#{key}", val) end + elsif context + context.instance_variables.each do |name| + instance_variable_set(name, context.instance_variable_get(name)) + end + end + return instance_eval(_src, (@filename || '(erubis)')) + end + + end + + + ## + ## return array instead of string + ## + ## this is only for Eruby. + ## + module ArrayEnhancer + + def self.desc # :nodoc: + "return array instead of string" + end + + def add_preamble(src) + src << "#{@bufvar} = [];" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}\n" + end + + end + + + ## + ## use an Array object as buffer (included in Eruby by default) + ## + ## this is only for Eruby. + ## + module ArrayBufferEnhancer + + def self.desc # :nodoc: + "use an Array object for buffering (included in Eruby class)" + end + + def add_preamble(src) + src << "_buf = [];" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "_buf.join\n" + end + + end + + + ## + ## use String class for buffering + ## + ## this is only for Eruby. + ## + module StringBufferEnhancer + + def self.desc # :nodoc: + "use a String object for buffering" + end + + def add_preamble(src) + src << "#{@bufvar} = '';" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}.to_s\n" + end + + end + + + ## + ## use StringIO class for buffering + ## + ## this is only for Eruby. + ## + module StringIOEnhancer # :nodoc: + + def self.desc # :nodoc: + "use a StringIO object for buffering" + end + + def add_preamble(src) + src << "#{@bufvar} = StringIO.new;" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}.string\n" + end + + end + + + ## + ## set buffer variable name to '_erbout' as well as '_buf' + ## + ## this is only for Eruby. + ## + module ErboutEnhancer + + def self.desc # :nodoc: + "set '_erbout = _buf = \"\";' to be compatible with ERB." + end + + def add_preamble(src) + src << "_erbout = #{@bufvar} = '';" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}.to_s\n" + end + + end + + + ## + ## remove text and leave code, especially useful when debugging. + ## + ## ex. + ## $ erubis -s -E NoText file.eruby | more + ## + ## this is language independent. + ## + module NoTextEnhancer + + def self.desc # :nodoc: + "remove text and leave code (useful when debugging)" + end + + def add_text(src, text) + src << ("\n" * text.count("\n")) + if text[-1] != ?\n + text =~ /^(.*?)\z/ + src << (' ' * $1.length) + end + end + + end + + + ## + ## remove code and leave text, especially useful when validating HTML tags. + ## + ## ex. + ## $ erubis -s -E NoCode file.eruby | tidy -errors + ## + ## this is language independent. + ## + module NoCodeEnhancer + + def self.desc # :nodoc: + "remove code and leave text (useful when validating HTML)" + end + + def add_preamble(src) + end + + def add_postamble(src) + end + + def add_text(src, text) + src << text + end + + def add_expr(src, code, indicator) + src << "\n" * code.count("\n") + end + + def add_stmt(src, code) + src << "\n" * code.count("\n") + end + + end + + + ## + ## get convert faster, but spaces around '<%...%>' are not trimmed. + ## + ## this is language-independent. + ## + module SimplifyEnhancer + + def self.desc # :nodoc: + "get convert faster but leave spaces around '<% %>'" + end + + #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + SIMPLE_REGEXP = /<%(=+|\#)?(.*?)-?%>/m + + def convert(input) + src = "" + add_preamble(src) + #regexp = pattern_regexp(@pattern) + pos = 0 + input.scan(SIMPLE_REGEXP) do |indicator, code| + match = Regexp.last_match + index = match.begin(0) + text = input[pos, index - pos] + pos = match.end(0) + add_text(src, text) + if !indicator # <% %> + add_stmt(src, code) + elsif indicator[0] == ?\# # <%# %> + n = code.count("\n") + add_stmt(src, "\n" * n) + else # <%= %> + add_expr(src, code, indicator) + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(src, rest) + add_postamble(src) + return src + end + + end + + + ## + ## enable to use other embedded expression pattern (default is '\[= =\]'). + ## + ## notice! this is an experimental. spec may change in the future. + ## + ## ex. + ## input = < + ## <%= item %> : <%== item %> + ## [= item =] : [== item =] + ## <% end %> + ## END + ## + ## class BiPatternEruby + ## include BiPatternEnhancer + ## end + ## eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]') + ## list = ['', 'b&b', '"c"'] + ## print eruby.result(binding()) + ## + ## ## output + ## : <a> + ## : <a> + ## b&b : b&b + ## b&b : b&b + ## "c" : "c" + ## "c" : "c" + ## + ## this is language independent. + ## + module BiPatternEnhancer + + def self.desc # :nodoc: + "another embedded expression pattern (default '\[= =\]')." + end + + def initialize(input, properties={}) + self.bipattern = properties[:bipattern] # or '\$\{ \}' + super + end + + ## when pat is nil then '\[= =\]' is used + def bipattern=(pat) # :nodoc: + @bipattern = pat || '\[= =\]' + pre, post = @bipattern.split() + @bipattern_regexp = /(.*?)#{pre}(=*)(.*?)#{post}/m + end + + def add_text(src, text) + return unless text + m = nil + text.scan(@bipattern_regexp) do |txt, indicator, code| + m = Regexp.last_match + super(src, txt) + add_expr(src, code, '=' + indicator) + end + #rest = $' || text # ruby1.8 + rest = m ? text[m.end(0)..-1] : text # ruby1.9 + super(src, rest) + end + + end + + + ## + ## regards lines starting with '^[ \t]*%' as program code + ## + ## in addition you can specify prefix character (default '%') + ## + ## this is language-independent. + ## + module PrefixedLineEnhancer + + def self.desc # :nodoc: + "regard lines matched to '^[ \t]*%' as program code" + end + + def init_generator(properties={}) + super + @prefixchar = properties[:prefixchar] + end + + def add_text(src, text) + unless @prefixrexp + @prefixchar ||= '%' + @prefixrexp = Regexp.compile("^([ \\t]*)\\#{@prefixchar}(.*?\\r?\\n)") + end + pos = 0 + text2 = '' + text.scan(@prefixrexp) do + space = $1 + line = $2 + space, line = '', $1 unless $2 + match = Regexp.last_match + len = match.begin(0) - pos + str = text[pos, len] + pos = match.end(0) + if text2.empty? + text2 = str + else + text2 << str + end + if line[0, 1] == @prefixchar + text2 << space << line + else + super(src, text2) + text2 = '' + add_stmt(src, space + line) + end + end + #rest = pos == 0 ? text : $' # ruby1.8 + rest = pos == 0 ? text : text[pos..-1] # ruby1.9 + unless text2.empty? + text2 << rest if rest + rest = text2 + end + super(src, rest) + end + + end + + + ## + ## regards lines starting with '%' as program code + ## + ## this is for compatibility to eruby and ERB. + ## + ## this is language-independent. + ## + module PercentLineEnhancer + include PrefixedLineEnhancer + + def self.desc # :nodoc: + "regard lines starting with '%' as program code" + end + + #-- + #def init_generator(properties={}) + # super + # @prefixchar = '%' + # @prefixrexp = /^\%(.*?\r?\n)/ + #end + #++ + + def add_text(src, text) + unless @prefixrexp + @prefixchar = '%' + @prefixrexp = /^\%(.*?\r?\n)/ + end + super(src, text) + end + + end + + + ## + ## [experimental] allow header and footer in eRuby script + ## + ## ex. + ## ==================== + ## ## without header and footer + ## $ cat ex1.eruby + ## <% def list_items(list) %> + ## <% for item in list %> + ##
  • <%= item %>
  • + ## <% end %> + ## <% end %> + ## + ## $ erubis -s ex1.eruby + ## _buf = []; def list_items(list) + ## ; for item in list + ## ; _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • + ## '; end + ## ; end + ## ; + ## _buf.join + ## + ## ## with header and footer + ## $ cat ex2.eruby + ## + ## <% for item in list %> + ##
  • <%= item %>
  • + ## <% end %> + ## + ## + ## $ erubis -s -c HeaderFooterEruby ex4.eruby + ## + ## def list_items(list) + ## _buf = []; _buf << ' + ## '; for item in list + ## ; _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • + ## '; end + ## ; _buf << ' + ## '; + ## _buf.join + ## end + ## + ## ==================== + ## + ## this is language-independent. + ## + module HeaderFooterEnhancer + + def self.desc # :nodoc: + "allow header/footer in document (ex. '')" + end + + HEADER_FOOTER_PATTERN = /(.*?)(^[ \t]*)?([ \t]*\r?\n)?/m + + def add_text(src, text) + m = nil + text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace| + m = Regexp.last_match + flag_trim = @trim && lspace && rspace + super(src, txt) + content = "#{lspace}#{content}#{rspace}" if flag_trim + super(src, lspace) if !flag_trim && lspace + instance_variable_set("@#{word}", content) + super(src, rspace) if !flag_trim && rspace + end + #rest = $' || text # ruby1.8 + rest = m ? text[m.end(0)..-1] : text # ruby1.9 + super(src, rest) + end + + attr_accessor :header, :footer + + def convert(input) + source = super + return @src = "#{@header}#{source}#{@footer}" + end + + end + + + ## + ## delete indentation of HTML. + ## + ## this is language-independent. + ## + module DeleteIndentEnhancer + + def self.desc # :nodoc: + "delete indentation of HTML." + end + + def convert_input(src, input) + input = input.gsub(/^[ \t]+<%=title%>" into "_buf << %Q`

    #{title}

    `" + ## + ## this is only for Eruby. + ## + module InterpolationEnhancer + + def self.desc # :nodoc: + "convert '

    <%=text%>

    ' into '_buf << %Q`

    \#{text}

    `'" + end + + def convert_input(src, input) + pat = @pattern + regexp = pat.nil? || pat == '<% %>' ? Basic::Converter::DEFAULT_REGEXP : pattern_regexp(pat) + pos = 0 + is_bol = true # is beginning of line + str = '' + input.scan(regexp) do |indicator, code, tailch, rspace| + match = Regexp.last_match() + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + ch = indicator ? indicator[0] : nil + lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol) + is_bol = rspace ? true : false + _add_text_to_str(str, text) + ## * when '<%= %>', do nothing + ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>' + if ch == ?= # <%= %> + rspace = nil if tailch && !tailch.empty? + str << lspace if lspace + add_expr(str, code, indicator) + str << rspace if rspace + elsif ch == ?\# # <%# %> + n = code.count("\n") + (rspace ? 1 : 0) + if @trim && lspace && rspace + add_text(src, str) + str = '' + add_stmt(src, "\n" * n) + else + str << lspace if lspace + add_text(src, str) + str = '' + add_stmt(src, "\n" * n) + str << rspace if rspace + end + else # <% %> + if @trim && lspace && rspace + add_text(src, str) + str = '' + add_stmt(src, "#{lspace}#{code}#{rspace}") + else + str << lspace if lspace + add_text(src, str) + str = '' + add_stmt(src, code) + str << rspace if rspace + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + _add_text_to_str(str, rest) + add_text(src, str) + end + + def add_text(src, text) + return if !text || text.empty? + #src << " _buf << %Q`" << text << "`;" + if text[-1] == ?\n + text[-1] = "\\n" + src << " #{@bufvar} << %Q`#{text}`\n" + else + src << " #{@bufvar} << %Q`#{text}`;" + end + end + + def _add_text_to_str(str, text) + return if !text || text.empty? + str << text.gsub(/[`\#\\]/, '\\\\\&') + end + + def add_expr_escaped(str, code) + str << "\#{#{escaped_expr(code)}}" + end + + def add_expr_literal(str, code) + str << "\#{#{code}}" + end + + end + + +end +#--end of require 'erubis/enhancer' +#require 'erubis/tiny' +#--begin of require 'erubis/engine/eruby' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + ## + ## code generator for Ruby + ## + module RubyGenerator + include Generator + #include ArrayBufferEnhancer + include StringBufferEnhancer + + def init_generator(properties={}) + super + @escapefunc ||= "Erubis::XmlHelper.escape_xml" + @bufvar = properties[:bufvar] || "_buf" + end + + def self.supported_properties() # :nodoc: + return [] + end + + def escape_text(text) + text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\' + end + + def escaped_expr(code) + return "#{@escapefunc}(#{code})" + end + + #-- + #def add_preamble(src) + # src << "#{@bufvar} = [];" + #end + #++ + + def add_text(src, text) + src << " #{@bufvar} << '" << escape_text(text) << "';" unless text.empty? + end + + def add_stmt(src, code) + #src << code << ';' + src << code + src << ';' unless code[-1] == ?\n + end + + def add_expr_literal(src, code) + src << " #{@bufvar} << (" << code << ').to_s;' + end + + def add_expr_escaped(src, code) + src << " #{@bufvar} << " << escaped_expr(code) << ';' + end + + def add_expr_debug(src, code) + code.strip! + s = (code.dump =~ /\A"(.*)"\z/) && $1 + src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");' + end + + #-- + #def add_postamble(src) + # src << "\n#{@bufvar}.join\n" + #end + #++ + + end + + + ## + ## engine for Ruby + ## + class Eruby < Basic::Engine + include RubyEvaluator + include RubyGenerator + end + + + ## + ## fast engine for Ruby + ## + class FastEruby < Eruby + include InterpolationEnhancer + end + + + ## + ## swtich '<%= %>' to escaped and '<%== %>' to not escaped + ## + class EscapedEruby < Eruby + include EscapeEnhancer + end + + + ## + ## sanitize expression (<%= ... %>) by default + ## + ## this is equivalent to EscapedEruby and is prepared only for compatibility. + ## + class XmlEruby < Eruby + include EscapeEnhancer + end + + + class PI::Eruby < PI::Engine + include RubyEvaluator + include RubyGenerator + + def init_converter(properties={}) + @pi = 'rb' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/eruby' +#require 'erubis/engine/enhanced' # enhanced eruby engines +#require 'erubis/engine/optimized' # generates optimized ruby code +#require 'erubis/engine/ephp' +#require 'erubis/engine/ec' +#require 'erubis/engine/ejava' +#require 'erubis/engine/escheme' +#require 'erubis/engine/eperl' +#require 'erubis/engine/ejavascript' + +#--begin of require 'erubis/local-setting' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +## +## you can add site-local settings here. +## this files is required by erubis.rb +## +#--end of require 'erubis/local-setting' +#--end of require 'erubis' +#--begin of require 'erubis/tiny' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +module Erubis + + ## + ## tiny and the simplest implementation of eRuby + ## + ## ex. + ## eruby = TinyEruby.new(File.read('example.rhtml')) + ## print eruby.src # print ruby code + ## print eruby.result(binding()) # eval ruby code with Binding object + ## print eruby.evalute(context) # eval ruby code with context object + ## + class TinyEruby + + def initialize(input=nil) + @src = convert(input) if input + end + attr_reader :src + + EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m + + def convert(input) + src = "_buf = '';" # preamble + pos = 0 + input.scan(EMBEDDED_PATTERN) do |indicator, code| + m = Regexp.last_match + text = input[pos...m.begin(0)] + pos = m.end(0) + #src << " _buf << '" << escape_text(text) << "';" + text.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << text << "';" unless text.empty? + if !indicator # <% %> + src << code << ";" + elsif indicator == '#' # <%# %> + src << ("\n" * code.count("\n")) + else # <%= %> + src << " _buf << (" << code << ").to_s;" + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + #src << " _buf << '" << escape_text(rest) << "';" + rest.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << rest << "';" unless rest.empty? + src << "\n_buf.to_s\n" # postamble + return src + end + + #def escape_text(text) + # return text.gsub!(/['\\]/, '\\\\\&') || text + #end + + def result(_binding=TOPLEVEL_BINDING) + eval @src, _binding + end + + def evaluate(_context=Object.new) + if _context.is_a?(Hash) + _obj = Object.new + _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end + _context = _obj + end + _context.instance_eval @src + end + + end + + + + module PI + end + + class PI::TinyEruby + + def initialize(input=nil, options={}) + @escape = options[:escape] || 'Erubis::XmlHelper.escape_xml' + @src = convert(input) if input + end + + attr_reader :src + + EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m + + def convert(input) + src = "_buf = '';" # preamble + pos = 0 + input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr| + match = Regexp.last_match + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + #src << " _buf << '" << escape_text(text) << "';" + text.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << text << "';" unless text.empty? + if stmt # + if lspace && rspace + src << "#{lspace}#{stmt}#{rspace}" + else + src << " _buf << '" << lspace << "';" if lspace + src << stmt << ";" + src << " _buf << '" << rspace << "';" if rspace + end + else # ${...}, $!{...} + if !indicator + src << " _buf << " << @escape << "(" << expr << ");" + elsif indicator == '!' + src << " _buf << (" << expr << ").to_s;" + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + #src << " _buf << '" << escape_text(rest) << "';" + rest.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << rest << "';" unless rest.empty? + src << "\n_buf.to_s\n" # postamble + return src + end + + #def escape_text(text) + # return text.gsub!(/['\\]/, '\\\\\&') || text + #end + + def result(_binding=TOPLEVEL_BINDING) + eval @src, _binding + end + + def evaluate(_context=Object.new) + if _context.is_a?(Hash) + _obj = Object.new + _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end + _context = _obj + end + _context.instance_eval @src + end + + end + + +end +#--end of require 'erubis/tiny' +#--begin of require 'erubis/engine/enhanced' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/enhancer' +#--already included require 'erubis/engine/eruby' + + +module Erubis + + + #-- + ## moved to engine/ruby.rb + #class EscapedEruby < Eruby + # include EscapeEnhancer + #end + #++ + + + #-- + ### (obsolete) + #class FastEruby < Eruby + # include FastEnhancer + #end + #++ + + + class StdoutEruby < Eruby + include StdoutEnhancer + end + + + class PrintOutEruby < Eruby + include PrintOutEnhancer + end + + + class PrintEnabledEruby < Eruby + include PrintEnabledEnhancer + end + + + class ArrayEruby < Eruby + include ArrayEnhancer + end + + + class ArrayBufferEruby < Eruby + include ArrayBufferEnhancer + end + + + class StringBufferEruby < Eruby + include StringBufferEnhancer + end + + + class StringIOEruby < Eruby + include StringIOEnhancer + end + + + class ErboutEruby < Eruby + include ErboutEnhancer + end + + + class NoTextEruby < Eruby + include NoTextEnhancer + end + + + class NoCodeEruby < Eruby + include NoCodeEnhancer + end + + + class SimplifiedEruby < Eruby + include SimplifyEnhancer + end + + + class StdoutSimplifiedEruby < Eruby + include StdoutEnhancer + include SimplifyEnhancer + end + + + class PrintOutSimplifiedEruby < Eruby + include PrintOutEnhancer + include SimplifyEnhancer + end + + + class BiPatternEruby < Eruby + include BiPatternEnhancer + end + + + class PercentLineEruby < Eruby + include PercentLineEnhancer + end + + + class PrefixedLineEruby < Eruby + include PrefixedLineEnhancer + end + + + class HeaderFooterEruby < Eruby + include HeaderFooterEnhancer + end + + + class DeleteIndentEruby < Eruby + include DeleteIndentEnhancer + end + + + class InterpolationEruby < Eruby + include InterpolationEnhancer + end + + +end +#--end of require 'erubis/engine/enhanced' +#--begin of require 'erubis/engine/optimized' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +#--already included require 'erubis/engine/eruby' + + +module Erubis + + + module OptimizedGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [] + end + + def init_generator(properties={}) + super + @escapefunc ||= "Erubis::XmlHelper.escape_xml" + @initialized = false + @prev_is_expr = false + end + + protected + + def escape_text(text) + text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\' + end + + def escaped_expr(code) + @escapefunc ||= 'Erubis::XmlHelper.escape_xml' + return "#{@escapefunc}(#{code})" + end + + def switch_to_expr(src) + return if @prev_is_expr + @prev_is_expr = true + src << ' _buf' + end + + def switch_to_stmt(src) + return unless @prev_is_expr + @prev_is_expr = false + src << ';' + end + + def add_preamble(src) + #@initialized = false + #@prev_is_expr = false + end + + def add_text(src, text) + return if text.empty? + if @initialized + switch_to_expr(src) + src << " << '" << escape_text(text) << "'" + else + src << "_buf = '" << escape_text(text) << "';" + @initialized = true + end + end + + def add_stmt(src, code) + switch_to_stmt(src) if @initialized + #super + src << code + src << ';' unless code[-1] == ?\n + end + + def add_expr_literal(src, code) + unless @initialized; src << "_buf = ''"; @initialized = true; end + switch_to_expr(src) + src << " << (" << code << ").to_s" + end + + def add_expr_escaped(src, code) + unless @initialized; src << "_buf = ''"; @initialized = true; end + switch_to_expr(src) + src << " << " << escaped_expr(code) + end + + def add_expr_debug(src, code) + code.strip! + s = (code.dump =~ /\A"(.*)"\z/) && $1 + src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");' + end + + def add_postamble(src) + #super if @initialized + src << "\n_buf\n" if @initialized + end + + end # end of class OptimizedEruby + + + ## + ## Eruby class which generates optimized ruby code + ## + class OptimizedEruby < Basic::Engine # Eruby + include RubyEvaluator + include OptimizedGenerator + + def init_converter(properties={}) + @pi = 'rb' + super(properties) + end + + end + + + ## + ## XmlEruby class which generates optimized ruby code + ## + class OptimizedXmlEruby < OptimizedEruby + include EscapeEnhancer + + def add_expr_debug(src, code) + switch_to_stmt(src) if indicator == '===' && !@initialized + super + end + + end # end of class OptimizedXmlEruby + +end +#--end of require 'erubis/engine/optimized' +#--already included require 'erubis/engine/eruby' +#--begin of require 'erubis/engine/ephp' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module PhpGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'htmlspecialchars' + end + + def add_preamble(src) + # empty + end + + def escape_text(text) + return text.gsub!(/<\?xml\b/, '<?xml') || text + end + + def add_text(src, text) + src << escape_text(text) + end + + def add_expr_literal(src, code) + code.strip! + src << "" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + code.strip! + s = code.gsub(/\'/, "\\'") + src << "" + end + + def add_stmt(src, code) + src << "\n" + else + src << code << "?>" + end + end + + def add_postamble(src) + # empty + end + + end + + + ## + ## engine for PHP + ## + class Ephp < Basic::Engine + include PhpGenerator + end + + + class EscapedEphp < Ephp + include EscapeEnhancer + end + + + #class XmlEphp < Ephp + # include EscapeEnhancer + #end + + + class PI::Ephp < PI::Engine + include PhpGenerator + + def init_converter(properties={}) + @pi = 'php' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/ephp' +#--begin of require 'erubis/engine/ec' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module CGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:indent, '', "indent spaces (ex. ' ')"], + [:out, 'stdout', "output file pointer name"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= "escape" + @indent = properties[:indent] || '' + @out = properties[:out] || 'stdout' + end + + def add_preamble(src) + src << "#line 1 \"#{self.filename}\"\n" if self.filename + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } + return text + end + + def escaped_expr(code) + return "#{@escapefunc}(#{code.strip}, #{@out})" + end + + def add_text(src, text) + return if text.empty? + src << (src.empty? || src[-1] == ?\n ? @indent : ' ') + src << "fputs(" + i = 0 + text.each_line do |line| + src << "\n" << @indent << ' ' if i > 0 + i += 1 + src << '"' << escape_text(line) << '"' + end + src << ", #{@out});" #<< (text[-1] == ?\n ? "\n" : "") + src << "\n" if text[-1] == ?\n + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << " fprintf(#{@out}, " << code.strip << ');' + end + + def add_expr_escaped(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << ' ' << escaped_expr(code) << ';' + end + + def add_expr_debug(src, code) + code.strip! + s = nil + if code =~ /\A\".*?\"\s*,\s*(.*)/ + s = $1.gsub(/[%"]/, '\\\1') + '=' + end + src << @indent if src.empty? || src[-1] == ?\n + src << " fprintf(stderr, \"*** debug: #{s}\" #{code});" + end + + def add_postamble(src) + # empty + end + + end + + + ## + ## engine for C + ## + class Ec < Basic::Engine + include CGenerator + end + + + class EscapedEc < Ec + include EscapeEnhancer + end + + + #class XmlEc < Ec + # include EscapeEnhancer + #end + + class PI::Ec < PI::Engine + include CGenerator + + def init_converter(properties={}) + @pi = 'c' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/ec' +#--begin of require 'erubis/engine/ecpp' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module CppGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:indent, '', "indent spaces (ex. ' ')"], + [:bufvar, '_buf', "buffer variable name"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= "escape" + @indent = properties[:indent] || '' + @bufvar = properties[:bufvar] || '_buf' + end + + def add_preamble(src) + src << "#line 1 \"#{self.filename}\"\n" if self.filename + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } + return text + end + + def escaped_expr(code) + return "#{@escapefunc}(#{code.strip})" + end + + def add_text(src, text) + return if text.empty? + src << (src.empty? || src[-1] == ?\n ? @indent : ' ') + src << "_buf << " + i = 0 + text.each_line do |line| + src << "\n" << @indent << " " if i > 0 + i += 1 + src << '"' << escape_text(line) << '"' + end + src << ";" #<< (text[-1] == ?\n ? "\n" : "") + src << "\n" if text[-1] == ?\n + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << " _buf << (" << code.strip << ");" + end + + def add_expr_escaped(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << ' ' << escaped_expr(code) << ';' + end + + def add_expr_debug(src, code) + code.strip! + src << @indent if src.empty? || src[-1] == ?\n + src << " std::cerr << \"*** debug: #{code.gsub(/(")/, '\\\&')}=\" << (#{code});" + end + + def add_postamble(src) + # empty + end + + end + + + ## + ## engine for C + ## + class Ecpp < Basic::Engine + include CppGenerator + end + + + class EscapedEcpp < Ecpp + include EscapeEnhancer + end + + + #class XmlEcpp < Ecpp + # include EscapeEnhancer + #end + + class PI::Ecpp < PI::Engine + include CppGenerator + + def init_converter(properties={}) + @pi = 'cpp' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/ecpp' +#--begin of require 'erubis/engine/ejava' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module JavaGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:indent, '', "indent spaces (ex. ' ')"], + [:bufvar, '_buf', "output buffer variable name"], + [:bufclass, 'StringBuffer', "output buffer class (ex. 'StringBuilder')"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'escape' + @indent = properties[:indent] || '' + @bufvar = properties[:bufvar] || '_buf' + @bufclass = properties[:bufclass] || 'StringBuffer' + end + + def add_preamble(src) + src << "#{@indent}#{@bufclass} #{@bufvar} = new #{@bufclass}();" + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text + end + + def add_text(src, text) + return if text.empty? + src << (src.empty? || src[-1] == ?\n ? @indent : ' ') + src << @bufvar << ".append(" + i = 0 + text.each_line do |line| + src << "\n" << @indent << ' + ' if i > 0 + i += 1 + src << '"' << escape_text(line) << '"' + end + src << ");" << (text[-1] == ?\n ? "\n" : "") + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + src << @indent if src.empty? || src[-1] == ?\n + code.strip! + src << " #{@bufvar}.append(#{code});" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + code.strip! + src << @indent if src.empty? || src[-1] == ?\n + src << " System.err.println(\"*** debug: #{code}=\"+(#{code}));" + end + + def add_postamble(src) + src << "\n" if src[-1] == ?; + src << @indent << "return " << @bufvar << ".toString();\n" + #src << @indent << "System.out.print(" << @bufvar << ".toString());\n" + end + + end + + + ## + ## engine for Java + ## + class Ejava < Basic::Engine + include JavaGenerator + end + + + class EscapedEjava < Ejava + include EscapeEnhancer + end + + + #class XmlEjava < Ejava + # include EscapeEnhancer + #end + + class PI::Ejava < PI::Engine + include JavaGenerator + + def init_converter(properties={}) + @pi = 'java' + super(properties) + end + + end + +end +#--end of require 'erubis/engine/ejava' +#--begin of require 'erubis/engine/escheme' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module SchemeGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:func, '_add', "function name (ex. 'display')"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'escape' + @func = properties[:func] || '_add' # or 'display' + end + + def add_preamble(src) + return unless @func == '_add' + src << "(let ((_buf '())) " + \ + "(define (_add x) (set! _buf (cons x _buf))) " + #src << "(let* ((_buf '())" + \ + # " (_add (lambda (x) (set! _buf (cons x _buf))))) " + end + + def escape_text(text) + @table_ ||= { '"'=>'\\"', '\\'=>'\\\\' } + text.gsub!(/["\\]/) { |m| @table_[m] } + return text + end + + def escaped_expr(code) + code.strip! + return "(#{@escapefunc} #{code})" + end + + def add_text(src, text) + return if text.empty? + t = escape_text(text) + if t[-1] == ?\n + t[-1, 1] = '' + src << "(#{@func} \"" << t << "\\n\")\n" + else + src << "(#{@func} \"" << t << '")' + end + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + code.strip! + src << "(#{@func} #{code})" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + s = (code.strip! || code).gsub(/\"/, '\\"') + src << "(display \"*** debug: #{s}=\")(display #{code.strip})(display \"\\n\")" + end + + def add_postamble(src) + return unless @func == '_add' + src << "\n" unless src[-1] == ?\n + src << " (reverse _buf))\n" + end + + end + + + ## + ## engine for Scheme + ## + class Escheme < Basic::Engine + include SchemeGenerator + end + + + class EscapedEscheme < Escheme + include EscapeEnhancer + end + + + #class XmlEscheme < Escheme + # include EscapeEnhancer + #end + + + class PI::Escheme < PI::Engine + include SchemeGenerator + + def init_converter(properties={}) + @pi = 'scheme' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/escheme' +#--begin of require 'erubis/engine/eperl' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module PerlGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:func, 'print', "function name"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'encode_entities' + @func = properties[:func] || 'print' + end + + def add_preamble(src) + src << "use HTML::Entities; "; + end + + def escape_text(text) + return text.gsub!(/['\\]/, '\\\\\&') || text + end + + def add_text(src, text) + src << @func << "('" << escape_text(text) << "'); " unless text.empty? + end + + def add_expr_literal(src, code) + code.strip! + src << @func << "(" << code << "); " + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + code.strip! + s = code.gsub(/\'/, "\\'") + src << @func << "('*** debug: #{code}=', #{code}, \"\\n\");" + end + + def add_stmt(src, code) + src << code + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + end + + end + + + ## + ## engine for Perl + ## + class Eperl < Basic::Engine + include PerlGenerator + end + + + class EscapedEperl < Eperl + include EscapeEnhancer + end + + + #class XmlEperl < Eperl + # include EscapeEnhancer + #end + + + class PI::Eperl < PI::Engine + include PerlGenerator + + def init_converter(properties={}) + @pi = 'perl' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/eperl' +#--begin of require 'erubis/engine/ejavascript' +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +#--already included require 'erubis/engine' +#--already included require 'erubis/enhancer' + + +module Erubis + + + module JavascriptGenerator + include Generator + + def self.supported_properties() # :nodoc: + list = [] + #list << [:indent, '', "indent spaces (ex. ' ')"] + #list << [:bufvar, '_buf', "output buffer variable name"] + list << [:docwrite, true, "use 'document.write()' when true"] + return list + end + + def init_generator(properties={}) + super + @escapefunc ||= 'escape' + @indent = properties[:indent] || '' + @bufvar = properties[:bufvar] || '_buf' + @docwrite = properties[:docwrite] != false # '!= false' will be removed in the next release + end + + def add_preamble(src) + src << "#{@indent}var #{@bufvar} = [];" + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n\\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text + end + + def add_indent(src, indent) + src << (src.empty? || src[-1] == ?\n ? indent : ' ') + end + + def add_text(src, text) + return if text.empty? + add_indent(src, @indent) + src << @bufvar << '.push("' + s = escape_text(text) + if s[-1] == ?\n + s[-2, 2] = '' + src << s << "\");\n" + else + src << s << "\");" + end + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + add_indent(src, @indent) + code.strip! + src << "#{@bufvar}.push(#{code});" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + add_indent(src, @indent) + code.strip! + src << "alert(\"*** debug: #{code}=\"+(#{code}));" + end + + def add_postamble(src) + src << "\n" if src[-1] == ?; + if @docwrite + src << @indent << 'document.write(' << @bufvar << ".join(\"\"));\n" + else + src << @indent << @bufvar << ".join(\"\");\n" + end + end + + end + + + ## + ## engine for JavaScript + ## + class Ejavascript < Basic::Engine + include JavascriptGenerator + end + + + class EscapedEjavascript < Ejavascript + include EscapeEnhancer + end + + + #class XmlEjavascript < Ejavascript + # include EscapeEnhancer + #end + + + class PI::Ejavascript < PI::Engine + include JavascriptGenerator + + def init_converter(properties={}) + @pi = 'js' + super(properties) + end + + end + + +end +#--end of require 'erubis/engine/ejavascript' + + +module Erubis + + + Ejs = Ejavascript + EscapedEjs = EscapedEjavascript + + + class CommandOptionError < ErubisError + end + + + ## + ## main class of command + ## + ## ex. + ## Main.main(ARGV) + ## + class Main + + def self.main(argv=ARGV) + status = 0 + begin + Main.new.execute(ARGV) + rescue CommandOptionError => ex + $stderr.puts ex.message + status = 1 + end + exit(status) + end + + def initialize + @single_options = "hvxztTSbeBXNUC" + @arg_options = "pcrfKIlaE" #C + @option_names = { + 'h' => :help, + 'v' => :version, + 'x' => :source, + 'z' => :syntax, + 'T' => :unexpand, + 't' => :untabify, # obsolete + 'S' => :intern, + 'b' => :bodyonly, + 'B' => :binding, + 'p' => :pattern, + 'c' => :context, + #'C' => :class, + 'e' => :escape, + 'r' => :requires, + 'f' => :datafiles, + 'K' => :kanji, + 'I' => :includes, + 'l' => :lang, + 'a' => :action, + 'E' => :enhancers, + 'X' => :notext, + 'N' => :linenum, + 'U' => :unique, + 'C' => :compact, + } + assert unless @single_options.length + @arg_options.length == @option_names.length + (@single_options + @arg_options).each_byte do |ch| + assert unless @option_names.key?(ch.chr) + end + end + + + def execute(argv=ARGV) + ## parse command-line options + options, properties = parse_argv(argv, @single_options, @arg_options) + filenames = argv + options['h'] = true if properties[:help] + opts = Object.new + arr = @option_names.collect {|ch, name| "def #{name}; @#{name}; end\n" } + opts.instance_eval arr.join + options.each do |ch, val| + name = @option_names[ch] + opts.instance_variable_set("@#{name}", val) + end + + ## help, version, enhancer list + if opts.help || opts.version + puts version() if opts.version + puts usage() if opts.help + puts show_properties() if opts.help + puts show_enhancers() if opts.help + return + end + + ## include path + opts.includes.split(/,/).each do |path| + $: << path + end if opts.includes + + ## require library + opts.requires.split(/,/).each do |library| + require library + end if opts.requires + + ## action + action = opts.action + action ||= 'syntax' if opts.syntax + action ||= 'convert' if opts.source || opts.notext + + ## lang + lang = opts.lang || 'ruby' + action ||= 'convert' if opts.lang + + ## class name of Eruby + #classname = opts.class + classname = nil + klass = get_classobj(classname, lang, properties[:pi]) + + ## kanji code + $KCODE = opts.kanji if opts.kanji + + ## read context values from yaml file + datafiles = opts.datafiles + context = load_datafiles(datafiles, opts) + + ## parse context data + if opts.context + context = parse_context_data(opts.context, opts) + end + + ## properties for engine + properties[:escape] = true if opts.escape && !properties.key?(:escape) + properties[:pattern] = opts.pattern if opts.pattern + #properties[:trim] = false if opts.notrim + properties[:preamble] = properties[:postamble] = false if opts.bodyonly + properties[:pi] = nil if properties[:pi] == true + + ## create engine and extend enhancers + engine = klass.new(nil, properties) + enhancers = get_enhancers(opts.enhancers) + #enhancers.push(Erubis::EscapeEnhancer) if opts.escape + enhancers.each do |enhancer| + engine.extend(enhancer) + engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer + end + + ## no-text + engine.extend(Erubis::NoTextEnhancer) if opts.notext + + ## convert and execute + val = nil + msg = "Syntax OK\n" + if filenames && !filenames.empty? + filenames.each do |filename| + File.file?(filename) or + raise CommandOptionError.new("#{filename}: file not found.") + engine.filename = filename + engine.convert!(File.read(filename)) + val = do_action(action, engine, context, filename, opts) + msg = nil if val + end + else + engine.filename = filename = '(stdin)' + engine.convert!($stdin.read()) + val = do_action(action, engine, context, filename, opts) + msg = nil if val + end + print msg if action == 'syntax' && msg + + end + + private + + def do_action(action, engine, context, filename, opts) + case action + when 'convert' + s = manipulate_src(engine.src, opts) + when nil, 'exec', 'execute' + s = opts.binding ? engine.result(context.to_hash) : engine.evaluate(context) + when 'syntax' + s = check_syntax(filename, engine.src) + else + raise "*** internal error" + end + print s if s + return s + end + + def manipulate_src(source, opts) + flag_linenum = opts.linenum + flag_unique = opts.unique + flag_compact = opts.compact + if flag_linenum + n = 0 + source.gsub!(/^/) { n += 1; "%5d: " % n } + source.gsub!(/^ *\d+:\s+?\n/, '') if flag_compact + source.gsub!(/(^ *\d+:\s+?\n)+/, "\n") if flag_unique + else + source.gsub!(/^\s*?\n/, '') if flag_compact + source.gsub!(/(^\s*?\n)+/, "\n") if flag_unique + end + return source + end + + def usage(command=nil) + command ||= File.basename($0) + buf = [] + buf << "erubis - embedded program converter for multi-language" + buf << "Usage: #{command} [..options..] [file ...]" + buf << " -h, --help : help" + buf << " -v : version" + buf << " -x : show converted code" + buf << " -X : show converted code, only ruby code and no text part" + buf << " -N : numbering: add line numbers (for '-x/-X')" + buf << " -U : unique: compress empty lines to a line (for '-x/-X')" + buf << " -C : compact: remove empty lines (for '-x/-X')" + buf << " -b : body only: no preamble nor postamble (for '-x/-X')" + buf << " -z : syntax checking" + buf << " -e : escape (equal to '--E Escape')" + buf << " -p pattern : embedded pattern (default '<% %>')" + buf << " -l lang : convert but no execute (ruby/php/c/cpp/java/scheme/perl/js)" + buf << " -E e1,e2,... : enhancer names (Escape, PercentLine, BiPattern, ...)" + buf << " -I path : library include path" + buf << " -K kanji : kanji code (euc/sjis/utf8) (default none)" + buf << " -c context : context data string (yaml inline style or ruby code)" + buf << " -f datafile : context data file ('*.yaml', '*.yml', or '*.rb')" + #buf << " -t : expand tab characters in YAML file" + buf << " -T : don't expand tab characters in YAML file" + buf << " -S : convert mapping key from string to symbol in YAML file" + buf << " -B : invoke 'result(binding)' instead of 'evaluate(context)'" + buf << " --pi=name : parse '' instead of '<% ... %>'" + #' + # -T : don't trim spaces around '<% %>' + # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby) + # -r library : require library + # -a : action (convert/execute) + return buf.join("\n") + end + + def collect_supported_properties(erubis_klass) + list = [] + erubis_klass.ancestors.each do |klass| + if klass.respond_to?(:supported_properties) + list.concat(klass.supported_properties) + end + end + return list + end + + def show_properties + s = "supported properties:\n" + basic_props = collect_supported_properties(Erubis::Basic::Engine) + pi_props = collect_supported_properties(Erubis::PI::Engine) + list = [] + common_props = basic_props & pi_props + list << ['(common)', common_props] + list << ['(basic)', basic_props - common_props] + list << ['(pi)', pi_props - common_props] + %w[ruby php c cpp java scheme perl javascript].each do |lang| + klass = Erubis.const_get("E#{lang}") + list << [lang, collect_supported_properties(klass) - basic_props] + end + list.each do |lang, props| + s << " * #{lang}\n" + props.each do |name, default_val, desc| + s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc]) + end + end + s << "\n" + return s + end + + def show_enhancers + dict = {} + ObjectSpace.each_object(Module) do |mod| + dict[$1] = mod if mod.name =~ /\AErubis::(.*)Enhancer\z/ + end + s = "enhancers:\n" + dict.sort_by {|name, mod| name }.each do |name, mod| + s << (" %-13s : %s\n" % [name, mod.desc]) + end + return s + end + + def version + return Erubis::VERSION + end + + def parse_argv(argv, arg_none='', arg_required='', arg_optional='') + options = {} + context = {} + while argv[0] && argv[0][0] == ?- + optstr = argv.shift + optstr = optstr[1, optstr.length-1] + # + if optstr[0] == ?- # context + optstr =~ /\A\-([-\w]+)(?:=(.*))?/ or + raise CommandOptionError.new("-#{optstr}: invalid context value.") + name, value = $1, $2 + name = name.gsub(/-/, '_').intern + #value = value.nil? ? true : YAML.load(value) # error, why? + value = value.nil? ? true : YAML.load("---\n#{value}\n") + context[name] = value + # + else # options + while optstr && !optstr.empty? + optchar = optstr[0].chr + optstr = optstr[1..-1] + if arg_none.include?(optchar) + options[optchar] = true + elsif arg_required.include?(optchar) + arg = optstr.empty? ? argv.shift : optstr or + raise CommandOptionError.new("-#{optchar}: #{@option_names[optchar]} required.") + options[optchar] = arg + optstr = nil + elsif arg_optional.include?(optchar) + arg = optstr.empty? ? true : optstr + options[optchar] = arg + optstr = nil + else + raise CommandOptionError.new("-#{optchar}: unknown option.") + end + end + end + # + end # end of while + + return options, context + end + + + def untabify(str, width=8) + list = str.split(/\t/) + last = list.pop + sb = '' + list.each do |s| + column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length + n = width - (column % width) + sb << s << (' ' * n) + end + sb << last + return sb + end + #-- + #def untabify(str, width=8) + # sb = '' + # str.scan(/(.*?)\t/m) do |s, | + # len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length + # sb << s << (" " * (width - len % width)) + # end + # return $' ? (sb << $') : str + #end + #++ + + + def get_classobj(classname, lang, pi) + classname ||= "E#{lang}" + base_module = pi ? Erubis::PI : Erubis + begin + klass = base_module.const_get(classname) + rescue NameError + klass = nil + end + unless klass + if lang + msg = "-l #{lang}: invalid language name (class #{base_module.name}::#{classname} not found)." + else + msg = "-c #{classname}: invalid class name." + end + raise CommandOptionError.new(msg) + end + return klass + end + + def get_enhancers(enhancer_names) + return [] unless enhancer_names + enhancers = [] + shortname = nil + begin + enhancer_names.split(/,/).each do |name| + shortname = name + enhancers << Erubis.const_get("#{shortname}Enhancer") + end + rescue NameError + raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-h' to show all enhancers).") + end + return enhancers + end + + def load_datafiles(filenames, opts) + context = Erubis::Context.new + return context unless filenames + filenames.split(/,/).each do |filename| + filename.strip! + test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.") + if filename =~ /\.ya?ml$/ + if opts.unexpand + ydoc = YAML.load_file(filename) + else + ydoc = YAML.load(untabify(File.read(filename))) + end + ydoc.is_a?(Hash) or raise CommandOptionError.new("#{filename}: root object is not a mapping.") + intern_hash_keys(ydoc) if opts.intern + context.update(ydoc) + elsif filename =~ /\.rb$/ + str = File.read(filename) + context2 = Erubis::Context.new + _instance_eval(context2, str) + context.update(context2) + else + CommandOptionError.new("#{filename}: '*.yaml', '*.yml', or '*.rb' required.") + end + end + return context + end + + def _instance_eval(_context, _str) + _context.instance_eval(_str) + end + + def parse_context_data(context_str, opts) + if context_str[0] == ?{ + require 'yaml' + ydoc = YAML.load(context_str) + unless ydoc.is_a?(Hash) + raise CommandOptionError.new("-c: root object is not a mapping.") + end + intern_hash_keys(ydoc) if opts.intern + return ydoc + else + context = Erubis::Context.new + context.instance_eval(context_str, '-c') + return context + end + end + + def intern_hash_keys(obj, done={}) + return if done.key?(obj.__id__) + case obj + when Hash + done[obj.__id__] = obj + obj.keys.each do |key| + obj[key.intern] = obj.delete(key) if key.is_a?(String) + end + obj.values.each do |val| + intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array) + end + when Array + done[obj.__id__] = obj + obj.each do |val| + intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array) + end + end + end + + def check_syntax(filename, src) + require 'open3' + #command = (ENV['_'] || 'ruby') + ' -wc' # ENV['_'] stores command name + bin = ENV['_'] && File.basename(ENV['_']) =~ /^ruby/ ? ENV['_'] : 'ruby' + command = bin + ' -wc' + stdin, stdout, stderr = Open3.popen3(command) + stdin.write(src) + stdin.close + result = stdout.read() + stdout.close() + errmsg = stderr.read() + stderr.close() + return nil unless errmsg && !errmsg.empty? + errmsg =~ /\A-:(\d+): / + linenum, message = $1, $' + return "#{filename}:#{linenum}: #{message}" + end + + if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx" + def check_syntax(filename, src) + require 'compiler' + verbose = $VERBOSE + msg = nil + begin + $VERBOSE = true + Rubinius::Compiler.compile_string(src, filename) + rescue SyntaxError => ex + ex_linenum = ex.line + linenum = 0 + srcline = src.each_line do |line| + linenum += 1 + break line if linenum == ex_linenum + end + msg = "#{ex.message}\n" + msg << srcline + msg << "\n" unless srcline =~ /\n\z/ + msg << (" " * (ex.column-1)) << "^\n" + ensure + $VERBOSE = verbose + end + return msg + end + end + + end + +end +#--end of require 'erubis/main' + +Erubis::Main.main(ARGV) diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis-run.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis-run.rb new file mode 100644 index 0000000..44be6d4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis-run.rb @@ -0,0 +1,132 @@ +=begin + += apache/erubis-run.rb + +Copyright (C) 2007 Andrew R Jackson + +Built from original by Shugo Maeda: +Copyright (C) 2001 Shugo Maeda + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WAreqANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WAreqANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTEreqUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +== Overview + +Apache::ErubisRun handles eRuby files with erubis + +== Example of httpd.conf + + RubyRequire apache/erubis-run + + SetHandler ruby-object + RubyHandler Apache::ErubisRun.instance + + +=end + +require "singleton" +require "tempfile" +require "eruby" # Still needed to bring in a couple useful helper methods +require "erubis" + +module Erubis + @@cgi = nil + + def self.cgi + return @@cgi + end + + def self.cgi=(cgi) + @@cgi = cgi + end +end + +module Apache + class ErubisRun + include Singleton + + def handler(req) + status = check_request(req) + return status if(status != OK) + + filename = req.filename.dup + filename.untaint + erubis = compile(filename) + prerun(req) + begin + run(erubis, filename) + ensure + postrun(req) + end + + return OK + end + + private + + def initialize + @compiler = nil + end + + def check_request(req) + if(req.method_number == M_OPTIONS) + req.allowed |= (1 << M_GET) + req.allowed |= (1 << M_POST) + return DECLINED + end + if(req.finfo.mode == 0) + return NOT_FOUND + end + return OK + end + + def compile(filename) + @compiler = Erubis::Eruby.load_file(filename) # use caching version as much as possible + return @compiler + end + + def prerun(req) + Erubis.cgi = nil + req.setup_cgi_env + Apache.chdir_file(req.filename) + end + + def run(erubis, filename) + binding = eval_string_wrap("binding") + puts erubis.result(binding) # eval the code in the context of the same binding ERuby uses + end + + def postrun(req) + if(cgi = Erubis.cgi) + # TODO: pull the content type header from the cgi object, if set there? + elsif(req.sync_output or req.sync_header) + # Do nothing: header has already been sent + else + unless(req.content_type) + req.content_type = format("text/html;") + end + req.send_http_header + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/inline-require b/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/inline-require new file mode 100755 index 0000000..de420c6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/contrib/inline-require @@ -0,0 +1,179 @@ +#!/usr/bin/env ruby + +### +### inline-require - expand 'require "foo"' into inline code +### +### usage: inline-require [-h] [-I path[,path2,..]] script +### +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### 2.7.0 +### $Rev: 10 $ +### + + +class InlineRequire + + def initialize(opts={}) + @opts = opts.dup + end + attr_accessor :opts + + def expand(filename) + sbuf = '' + inlined = [] + level = 0 + expand_require(filename, sbuf, inlined, level) + return sbuf + end + + private + + def expand_require(filename, sbuf, inlined, level) + raise "*** assertion error" if inlined.include?(filename) + remove_comment = @opts[:remove_comment] + expand_indented = @opts[:expand_indented] + keep_filename = @opts[:keep_filename] + loaded_features = @opts[:loaded_features] + inlined << filename + prog = File.read(filename) + n = 0 + flag_if_file = false + prog.each_line do |line| + n += 1 + + ## comment out from 'if __FILE__ == $0' to 'end' + if level > 0 + if flag_if_file + sbuf << "#" << line + flag_if_file = false if line =~ /^end$/ + next + end + if line =~ /^if\s+__FILE__\s*==\s*\$0(\s+then)?$/ || line =~ /^if\s+\$0\s*==\s*__FILE__(\s+then)?$/ + flag_if_file = true + sbuf << "#" << line + next + end + end + + ## find 'require "foo"' and expand it to inline code + flag_inline = false + pattern = expand_indented ? /^[ \t]*require ['"](.*)["']\s*$/ \ + : /^require ['"](.*)["']\s*$/ + if line =~ pattern + libname = $1 + libpath = find_library(libname) + $stderr.puts "*** debug: libpath=#{libpath.inspect}" if $debug_mode + unless libpath + #raise "file '#{filename}'(line #{n}): library '#{libname}' not found." + warn "file '#{filename}'(line #{n}): library '#{libname}' not found." + else + flag_inline = true if libpath =~ /\.rb$/ && local_library?(libpath) + end + end + if !flag_inline + sbuf << line unless remove_comment && line =~ /^[ \t]*\#/ + elsif inlined.include?(libpath) + sbuf << "#--already included #{line}" unless remove_comment + else + if keep_filename + @n ||= 0; @n += 1; n = @n + end + sbuf << "#--begin of #{line}" unless remove_comment + sbuf << "$LOADED_FEATURES << '#{libname}.rb'\n" if loaded_features + sbuf << "eval <<'END_OF_SCRIPT__#{n}', TOPLEVEL_BINDING, '#{libpath}', 1\n" if keep_filename + expand_require(libpath, sbuf, inlined, level+1) + sbuf << "END_OF_SCRIPT__#{n}\n" if keep_filename + sbuf << "#--end of #{line}" unless remove_comment + end + end + #sbuf << "\n" if sbuf[-1] != ?\n + end + + def local_library?(libpath) + return libpath !~ /^\// + end + + def find_library(libname) + if libname =~ /^\.rb$/ + libname_rb = libname + libname_so = nil + elsif libname =~ /^\.so$/ + libname_rb = nil + libname_so = libname + else + libname_rb = libname + ".rb" + libname_so = libname + ".so" + end + $LOAD_PATH.each do |path| + if libname_rb + libpath = path + "/" + libname_rb + return libpath if test(?f, libpath) + end + if libname_so + libpath = path + "/" + libname_so + return libpath if test(?f, libpath) + end + end + return nil + end + +end + +if __FILE__ == $0 + + begin + require "optparse" + op = OptionParser.new + options = {} + op.on("-h", "--help") {|v| options[:help] = v } + op.on("-I libpath") {|v| options[:libpath] = v } + op.on("-i") {|v| options[:expand_indented] = v } + op.on("-c") {|v| options[:remove_comment] = v } + op.on("-k") {|v| options[:keep_filename] = v } + op.on("-l") {|v| options[:loaded_features] = v } + op.on("-D") {|v| options[:debug] = v } + op.parse!() + + $debug_mode = options[:debug] + + if options[:help] + command = File.basename($0) + puts "Usage: #{command} [-h] [-I path[,path2,..]] script" + puts " -h : help" + puts " -i : expand indented require(), too" + puts " -c : remove comment lines start with '#'" + puts " -k : keep filename (for debugging)" + puts " -l : append libs to $LOADED_FEATURES" + puts " -I path[,path2,...] : ruby library path" + exit(0) + end + + if options[:libpath] + rubylib_paths = options[:libpath].split(/,/) + else + rubylib_paths = [] + end + $stderr.puts "*** debug: rubylib_paths=#{rubylib_paths.inspect}" if $debug_mode + $LOAD_PATH.concat(rubylib_paths) + + filenames = ARGV + + opts = { :expand_indented => options[:expand_indented], + :remove_comment => options[:remove_comment], + :keep_filename => options[:keep_filename], + :loaded_features => options[:loaded_features] } + inline_require = InlineRequire.new(opts) + filenames.each do |filename| + print inline_require.expand(filename) + end + + rescue => ex + if $debug_mode + raise ex + else + $stderr.puts ex.message + end + + end + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ActionView.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ActionView.html new file mode 100644 index 0000000..2f9e153 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ActionView.html @@ -0,0 +1,105 @@ + + + + + + Module: ActionView + + + + + + + + + + +
    +
    #symbolnamepricechangeratio
    <%= n %> + <%= item['symbol'] %> + + <%= item['name'] %> + + <%= item['price'] %> + <%= item['change'] %><%= item['ratio'] %><%= item['change'] %><%= item['ratio'] %>
    <%= n %> + <%= item['symbol'] %> + + <%= item['name'] %> + + <%= item['price'] %> + <%= item['change'] %><%= item['ratio'] %><%= item['change'] %><%= item['ratio'] %>
    <%= n %> + <%= item['symbol'] %> + + <%= item['name'] %> + + <%= item['price'] %> + <%= item['change'] %><%= item['ratio'] %><%= item['change'] %><%= item['ratio'] %>
    + + + + + + + + + +
    ModuleActionView
    In: + + erubis/helpers/rails_helper.rb + +
    +
    + + + +
    + + + +
    + + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + +
    + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ActionView/TemplateHandlers/ErubisHandler.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ActionView/TemplateHandlers/ErubisHandler.html new file mode 100644 index 0000000..66b3c9b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ActionView/TemplateHandlers/ErubisHandler.html @@ -0,0 +1,209 @@ + + + + + + Class: ActionView::TemplateHandlers::ErubisHandler + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassActionView::TemplateHandlers::ErubisHandler
    In: + + erubis/helpers/rails_helper.rb + +
    +
    Parent: + TemplateHandler +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + +
    + compile   + compile   + compile   +
    +
    + +
    + + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 153
    +          def compile(template)
    +            #src = ::ERB.new("<% __in_erb_template=true %>#{template.source}", nil, erb_trim_mode, '@output_buffer').src
    +            return _convert_template("<% __in_erb_template=true %>#{template.source}")
    +          end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 179
    +          def compile(template)
    +            return _convert_template(template.source)   # template.is_a?(ActionView::Template)
    +          end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 209
    +          def compile(template)
    +            return _convert_template(template)     # template.is_a?(String)
    +          end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ERB.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ERB.html new file mode 100644 index 0000000..93ade5a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/ERB.html @@ -0,0 +1,101 @@ + + + + + + Module: ERB + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleERB
    In: +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis.html new file mode 100644 index 0000000..e5e636a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis.html @@ -0,0 +1,362 @@ + + + + + + Module: Erubis + + + + + + + + + + + + + +
    + + + +
    + +
    +

    +an implementation of eRuby +

    +

    +ex. +

    +
    +  input = <<'END'
    +   <ul>
    +    <% for item in @list %>
    +     <li><%= item %>
    +         <%== item %></li>
    +    <% end %>
    +   </ul>
    +  END
    +  list = ['<aaa>', 'b&b', '"ccc"']
    +  eruby = Erubis::Eruby.new(input)
    +  puts "--- code ---"
    +  puts eruby.src
    +  puts "--- result ---"
    +  context = Erubis::Context.new()   # or new(:list=>list)
    +  context[:list] = list
    +  puts eruby.evaluate(context)
    +
    +

    +result: +

    +
    +  --- source ---
    +  _buf = ''; _buf << '<ul>
    +  ';  for item in @list
    +   _buf << '  <li>'; _buf << ( item ).to_s; _buf << '
    +  '; _buf << '      '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</li>
    +  ';  end
    +   _buf << '</ul>
    +  ';
    +  _buf.to_s
    +  --- result ---
    +   <ul>
    +     <li><aaa>
    +         &lt;aaa&gt;</li>
    +     <li>b&b
    +         b&amp;b</li>
    +     <li>"ccc"
    +         &quot;ccc&quot;</li>
    +   </ul>
    +
    + +
    + + +
    + + +
    + + + + +
    + +
    +

    Classes and Modules

    + + Module Erubis::ArrayBufferEnhancer
    +Module Erubis::ArrayEnhancer
    +Module Erubis::Basic
    +Module Erubis::BiPatternEnhancer
    +Module Erubis::CGenerator
    +Module Erubis::Converter
    +Module Erubis::CppGenerator
    +Module Erubis::DeleteIndentEnhancer
    +Module Erubis::ErboutEnhancer
    +Module Erubis::EscapeEnhancer
    +Module Erubis::Evaluator
    +Module Erubis::Generator
    +Module Erubis::HeaderFooterEnhancer
    +Module Erubis::Helpers
    +Module Erubis::InterpolationEnhancer
    +Module Erubis::JavaGenerator
    +Module Erubis::JavascriptGenerator
    +Module Erubis::NoCodeEnhancer
    +Module Erubis::NoTextEnhancer
    +Module Erubis::OptimizedGenerator
    +Module Erubis::PI
    +Module Erubis::PercentLineEnhancer
    +Module Erubis::PerlGenerator
    +Module Erubis::PhpGenerator
    +Module Erubis::PrefixedLineEnhancer
    +Module Erubis::PreprocessingHelper
    +Module Erubis::PrintEnabledEnhancer
    +Module Erubis::PrintOutEnhancer
    +Module Erubis::RubyEvaluator
    +Module Erubis::RubyGenerator
    +Module Erubis::SchemeGenerator
    +Module Erubis::SimplifyEnhancer
    +Module Erubis::StdoutEnhancer
    +Module Erubis::StringBufferEnhancer
    +Module Erubis::XmlHelper
    +Class Erubis::ArrayBufferEruby
    +Class Erubis::ArrayEruby
    +Class Erubis::BiPatternEruby
    +Class Erubis::CommandOptionError
    +Class Erubis::Context
    +Class Erubis::DeleteIndentEruby
    +Class Erubis::Ec
    +Class Erubis::Ecpp
    +Class Erubis::Ejava
    +Class Erubis::Ejavascript
    +Class Erubis::Engine
    +Class Erubis::Eperl
    +Class Erubis::Ephp
    +Class Erubis::ErboutEruby
    +Class Erubis::ErubisError
    +Class Erubis::Eruby
    +Class Erubis::EscapedEc
    +Class Erubis::EscapedEcpp
    +Class Erubis::EscapedEjava
    +Class Erubis::EscapedEjavascript
    +Class Erubis::EscapedEperl
    +Class Erubis::EscapedEphp
    +Class Erubis::EscapedEruby
    +Class Erubis::EscapedEscheme
    +Class Erubis::Escheme
    +Class Erubis::FastEruby
    +Class Erubis::HeaderFooterEruby
    +Class Erubis::InterpolationEruby
    +Class Erubis::Main
    +Class Erubis::NoCodeEruby
    +Class Erubis::NoTextEruby
    +Class Erubis::NotSupportedError
    +Class Erubis::OptimizedEruby
    +Class Erubis::OptimizedXmlEruby
    +Class Erubis::PercentLineEruby
    +Class Erubis::PrefixedLineEruby
    +Class Erubis::PreprocessingEruby
    +Class Erubis::PrintEnabledEruby
    +Class Erubis::PrintOutEruby
    +Class Erubis::PrintOutSimplifiedEruby
    +Class Erubis::SimplifiedEruby
    +Class Erubis::StdoutEruby
    +Class Erubis::StdoutSimplifiedEruby
    +Class Erubis::StringBufferEruby
    +Class Erubis::StringIOEruby
    +Class Erubis::TinyEruby
    +Class Erubis::XmlEruby
    + +
    + +
    +

    Constants

    + +
    + + + + + + + + + + + + + + + + + + + + + +
    EMPTY_BINDING=binding()
    Ejs=Ejavascript
    EscapedEjs=EscapedEjavascript
    VERSION=('$Release: 2.7.0 $' =~ /([.\d]+)/) && $1
    +
    +
    + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayBufferEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayBufferEnhancer.html new file mode 100644 index 0000000..7f193f8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayBufferEnhancer.html @@ -0,0 +1,175 @@ + + + + + + Module: Erubis::ArrayBufferEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::ArrayBufferEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +use an Array object as buffer (included in Eruby +by default) +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_postamble   + add_preamble   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 191
    +    def add_postamble(src)
    +      src << "\n" unless src[-1] == ?\n
    +      src << "_buf.join\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 187
    +    def add_preamble(src)
    +      src << "_buf = [];"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayBufferEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayBufferEruby.html new file mode 100644 index 0000000..e4ee23a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayBufferEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::ArrayBufferEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::ArrayBufferEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayEnhancer.html new file mode 100644 index 0000000..e500513 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayEnhancer.html @@ -0,0 +1,174 @@ + + + + + + Module: Erubis::ArrayEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::ArrayEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +return array instead of string +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_postamble   + add_preamble   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 168
    +    def add_postamble(src)
    +      src << "\n" unless src[-1] == ?\n
    +      src << "#{@bufvar}\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 164
    +    def add_preamble(src)
    +      src << "#{@bufvar} = [];"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayEruby.html new file mode 100644 index 0000000..6d0c5d7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ArrayEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::ArrayEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::ArrayEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic.html new file mode 100644 index 0000000..068332e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic.html @@ -0,0 +1,112 @@ + + + + + + Module: Erubis::Basic + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Basic
    In: + + erubis/converter.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + + +
    + +
    +

    Classes and Modules

    + + Module Erubis::Basic::Converter
    +Class Erubis::Basic::Engine
    + +
    + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic/Converter.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic/Converter.html new file mode 100644 index 0000000..6ca06db --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic/Converter.html @@ -0,0 +1,327 @@ + + + + + + Module: Erubis::Basic::Converter + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Basic::Converter
    In: + + erubis/converter.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +basic converter which supports ’<% … %>’ notation. +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + +
    +

    Constants

    + +
    + + + + + + + + +
    DEFAULT_REGEXP=pattern_regexp('<% %>')  +DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m +DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m +DEFAULT_REGEXP = /<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + +
    +
    +
    + + + +
    +

    Attributes

    + +
    + + + + + + + + + + + +
    pattern [RW] 
    trim [RW] 
    +
    +
    + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    +add expression code to src +

    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 176
    +    def add_expr(src, code, indicator)
    +      case indicator
    +      when '='
    +        @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
    +      when '=='
    +        @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
    +      when '==='
    +        add_expr_debug(src, code)
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 127
    +    def convert_input(src, input)
    +      pat = @pattern
    +      regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat)
    +      pos = 0
    +      is_bol = true     # is beginning of line
    +      input.scan(regexp) do |indicator, code, tailch, rspace|
    +        match = Regexp.last_match()
    +        len  = match.begin(0) - pos
    +        text = input[pos, len]
    +        pos  = match.end(0)
    +        ch   = indicator ? indicator[0] : nil
    +        lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
    +        is_bol = rspace ? true : false
    +        add_text(src, text) if text && !text.empty?
    +        ## * when '<%= %>', do nothing
    +        ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
    +        if ch == ?=              # <%= %>
    +          rspace = nil if tailch && !tailch.empty?
    +          add_text(src, lspace) if lspace
    +          add_expr(src, code, indicator)
    +          add_text(src, rspace) if rspace
    +        elsif ch == ?\#          # <%# %>
    +          n = code.count("\n") + (rspace ? 1 : 0)
    +          if @trim && lspace && rspace
    +            add_stmt(src, "\n" * n)
    +          else
    +            add_text(src, lspace) if lspace
    +            add_stmt(src, "\n" * n)
    +            add_text(src, rspace) if rspace
    +          end
    +        elsif ch == ?%           # <%% %>
    +          s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}"
    +          add_text(src, s)
    +        else                     # <% %>
    +          if @trim && lspace && rspace
    +            add_stmt(src, "#{lspace}#{code}#{rspace}")
    +          else
    +            add_text(src, lspace) if lspace
    +            add_stmt(src, code)
    +            add_text(src, rspace) if rspace
    +          end
    +        end
    +      end
    +      #rest = $' || input                        # ruby1.8
    +      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
    +      add_text(src, rest)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 103
    +    def init_converter(properties={})
    +      super(properties)
    +      @pattern = properties[:pattern]
    +      @trim    = properties[:trim] != false
    +    end
    +
    +
    +
    +
    + +

    Protected Instance methods

    + +
    + + + + +
    +

    +return regexp of pattern to parse eRuby script +

    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 112
    +    def pattern_regexp(pattern)
    +      @prefix, @postfix = pattern.split()   # '<% %>' => '<%', '%>'
    +      #return /(.*?)(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m
    +      #return /(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m
    +      return /#{@prefix}(=+|-|\#|%)?(.*?)([-=])?#{@postfix}([ \t]*\r?\n)?/m
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic/Engine.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic/Engine.html new file mode 100644 index 0000000..3562b6f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Basic/Engine.html @@ -0,0 +1,130 @@ + + + + + + Class: Erubis::Basic::Engine + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Basic::Engine
    In: + + erubis/engine.rb + +
    +
    Parent: + + Engine + +
    +
    + + +
    + + + +
    + +
    +

    +(abstract) base engine class for Eruby, Eperl, Ejava, and so +on. subclass must include generator. +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/BiPatternEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/BiPatternEnhancer.html new file mode 100644 index 0000000..0c78878 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/BiPatternEnhancer.html @@ -0,0 +1,215 @@ + + + + + + Module: Erubis::BiPatternEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::BiPatternEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +enable to use other embedded expression pattern (default is ’\[= +=\]’). +

    +

    +notice! this is an experimental. spec may change in the future. +

    +

    +ex. +

    +
    +  input = <<END
    +  <% for item in list %>
    +    <%= item %> : <%== item %>
    +    [= item =] : [== item =]
    +  <% end %>
    +  END
    +
    +  class BiPatternEruby
    +    include BiPatternEnhancer
    +  end
    +  eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]')
    +  list = ['<a>', 'b&b', '"c"']
    +  print eruby.result(binding())
    +
    +  ## output
    +    <a> : &lt;a&gt;
    +    <a> : &lt;a&gt;
    +    b&b : b&amp;b
    +    b&b : b&amp;b
    +    "c" : &quot;c&quot;
    +    "c" : &quot;c&quot;
    +
    +

    +this is language independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_text   + new   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 408
    +    def initialize(input, properties={})
    +      self.bipattern = properties[:bipattern]    # or '\$\{ \}'
    +      super
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 420
    +    def add_text(src, text)
    +      return unless text
    +      m = nil
    +      text.scan(@bipattern_regexp) do |txt, indicator, code|
    +        m = Regexp.last_match
    +        super(src, txt)
    +        add_expr(src, code, '=' + indicator)
    +      end
    +      #rest = $' || text                    # ruby1.8
    +      rest = m ? text[m.end(0)..-1] : text  # ruby1.9
    +      super(src, rest)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/BiPatternEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/BiPatternEruby.html new file mode 100644 index 0000000..802420e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/BiPatternEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::BiPatternEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::BiPatternEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CGenerator.html new file mode 100644 index 0000000..d43a32e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CGenerator.html @@ -0,0 +1,386 @@ + + + + + + Module: Erubis::CGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::CGenerator
    In: + + erubis/engine/ec.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 72
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      s = nil
    +      if code =~ /\A\".*?\"\s*,\s*(.*)/
    +        s = $1.gsub(/[%"]/, '\\\1') + '='
    +      end
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << " fprintf(stderr, \"*** debug: #{s}\" #{code});"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 67
    +    def add_expr_escaped(src, code)
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << ' ' << escaped_expr(code) << ';'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 62
    +    def add_expr_literal(src, code)
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << " fprintf(#{@out}, " << code.strip << ');'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 82
    +    def add_postamble(src)
    +      # empty
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 30
    +    def add_preamble(src)
    +      src << "#line 1 \"#{self.filename}\"\n" if self.filename
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 58
    +    def add_stmt(src, code)
    +      src << code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 44
    +    def add_text(src, text)
    +      return if text.empty?
    +      src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
    +      src << "fputs("
    +      i = 0
    +      text.each_line do |line|
    +        src << "\n" << @indent << '      ' if i > 0
    +        i += 1
    +        src << '"' << escape_text(line) << '"'
    +      end
    +      src << ", #{@out});"   #<< (text[-1] == ?\n ? "\n" : "")
    +      src << "\n" if text[-1] == ?\n
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 34
    +    def escape_text(text)
    +      @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
    +      text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] }
    +      return text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 40
    +    def escaped_expr(code)
    +      return "#{@escapefunc}(#{code.strip}, #{@out})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 23
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= "escape"
    +      @indent = properties[:indent] || ''
    +      @out = properties[:out] || 'stdout'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CommandOptionError.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CommandOptionError.html new file mode 100644 index 0000000..e5d32a9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CommandOptionError.html @@ -0,0 +1,113 @@ + + + + + + Class: Erubis::CommandOptionError + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::CommandOptionError
    In: + + erubis/main.rb + +
    +
    Parent: + + ErubisError + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Context.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Context.html new file mode 100644 index 0000000..f27f40a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Context.html @@ -0,0 +1,344 @@ + + + + + + Class: Erubis::Context + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Context
    In: + + erubis/context.rb + +
    +
    Parent: + Object +
    +
    + + +
    + + + +
    + +
    +

    +context object for Engine#evaluate +

    +

    +ex. +

    +
    +  template = <<'END'
    +  Hello <%= @user %>!
    +  <% for item in @list %>
    +   - <%= item %>
    +  <% end %>
    +  END
    +
    +  context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
    +  # or
    +  # context = Erubis::Context.new
    +  # context[:user] = 'World'
    +  # context[:list] = ['a', 'b', 'c']
    +
    +  eruby = Erubis::Eruby.new(template)
    +  print eruby.evaluate(context)
    +
    + +
    + + +
    + +
    +

    Methods

    + +
    + []   + []=   + each   + keys   + new   + to_hash   + update   +
    +
    + +
    + + + +
    +

    Included Modules

    + +
    + Enumerable +
    +
    + +
    + + + + + + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 33
    +    def initialize(hash=nil)
    +      hash.each do |name, value|
    +        self[name] = value
    +      end if hash
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 39
    +    def [](key)
    +      return instance_variable_get("@#{key}")
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 43
    +    def []=(key, value)
    +      return instance_variable_set("@#{key}", value)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 51
    +    def each
    +      instance_variables.each do |name|
    +        key = name[1..-1]
    +        value = instance_variable_get(name)
    +        yield(key, value)
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 47
    +    def keys
    +      return instance_variables.collect { |name| name[1..-1] }
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 59
    +    def to_hash
    +      hash = {}
    +      self.keys.each { |key| hash[key] = self[key] }
    +      return hash
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/context.rb, line 65
    +    def update(context_or_hash)
    +      arg = context_or_hash
    +      if arg.is_a?(Hash)
    +        arg.each do |key, val|
    +          self[key] = val
    +        end
    +      else
    +        arg.instance_variables.each do |varname|
    +          key = varname[1..-1]
    +          val = arg.instance_variable_get(varname)
    +          self[key] = val
    +        end
    +      end
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Converter.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Converter.html new file mode 100644 index 0000000..a4b4bfe --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Converter.html @@ -0,0 +1,283 @@ + + + + + + Module: Erubis::Converter + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Converter
    In: + + erubis/converter.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +convert +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + + +
    + + + + + +
    +

    Attributes

    + +
    + + + + + + + + + + + + + + + + +
    escape [RW] 
    postamble [RW] 
    preamble [RW] 
    +
    +
    + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    +convert input string into target +language +

    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 33
    +    def convert(input)
    +      codebuf = ""    # or []
    +      @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
    +      convert_input(codebuf, input)
    +      @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
    +      @_proc = nil    # clear cached proc object
    +      return codebuf  # or codebuf.join()
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 26
    +    def init_converter(properties={})
    +      @preamble  = properties[:preamble]
    +      @postamble = properties[:postamble]
    +      @escape    = properties[:escape]
    +    end
    +
    +
    +
    +
    + +

    Protected Instance methods

    + +
    + + + + +
    +

    +(abstract) convert input to code +

    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 77
    +    def convert_input(codebuf, input)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +detect spaces at beginning of line +

    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 47
    +    def detect_spaces_at_bol(text, is_bol)
    +      lspace = nil
    +      if text.empty?
    +        lspace = "" if is_bol
    +      elsif text[-1] == ?\n
    +        lspace = ""
    +      else
    +        rindex = text.rindex(?\n)
    +        if rindex
    +          s = text[rindex+1..-1]
    +          if s =~ /\A[ \t]*\z/
    +            lspace = s
    +            #text = text[0..rindex]
    +            text[rindex+1..-1] = ''
    +          end
    +        else
    +          if is_bol && text =~ /\A[ \t]*\z/
    +            #lspace = text
    +            #text = nil
    +            lspace = text.dup
    +            text[0..-1] = ''
    +          end
    +        end
    +      end
    +      return lspace
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CppGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CppGenerator.html new file mode 100644 index 0000000..95213af --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/CppGenerator.html @@ -0,0 +1,382 @@ + + + + + + Module: Erubis::CppGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::CppGenerator
    In: + + erubis/engine/ecpp.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 72
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << " std::cerr << \"*** debug: #{code.gsub(/(")/, '\\\&')}=\" << (#{code});"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 67
    +    def add_expr_escaped(src, code)
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << ' ' << escaped_expr(code) << ';'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 62
    +    def add_expr_literal(src, code)
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << " _buf << (" << code.strip << ");"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 78
    +    def add_postamble(src)
    +      # empty
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 30
    +    def add_preamble(src)
    +      src << "#line 1 \"#{self.filename}\"\n" if self.filename
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 58
    +    def add_stmt(src, code)
    +      src << code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 44
    +    def add_text(src, text)
    +      return if text.empty?
    +      src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
    +      src << "_buf << "
    +      i = 0
    +      text.each_line do |line|
    +        src << "\n" << @indent << "        " if i > 0
    +        i += 1
    +        src << '"' << escape_text(line) << '"'
    +      end
    +      src << ";"   #<< (text[-1] == ?\n ? "\n" : "")
    +      src << "\n" if text[-1] == ?\n
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 34
    +    def escape_text(text)
    +      @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
    +      text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] }
    +      return text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 40
    +    def escaped_expr(code)
    +      return "#{@escapefunc}(#{code.strip})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 23
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= "escape"
    +      @indent = properties[:indent] || ''
    +      @bufvar = properties[:bufvar] || '_buf'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/DeleteIndentEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/DeleteIndentEnhancer.html new file mode 100644 index 0000000..ce450ef --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/DeleteIndentEnhancer.html @@ -0,0 +1,150 @@ + + + + + + Module: Erubis::DeleteIndentEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::DeleteIndentEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +delete indentation of HTML. +

    +

    +this is language-independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + convert_input   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 622
    +    def convert_input(src, input)
    +      input = input.gsub(/^[ \t]+</, '<')
    +      super(src, input)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/DeleteIndentEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/DeleteIndentEruby.html new file mode 100644 index 0000000..80720b9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/DeleteIndentEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::DeleteIndentEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::DeleteIndentEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ec.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ec.html new file mode 100644 index 0000000..9e880ba --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ec.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Ec + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Ec
    In: + + erubis/engine/ec.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for C +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ecpp.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ecpp.html new file mode 100644 index 0000000..a2866fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ecpp.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Ecpp + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Ecpp
    In: + + erubis/engine/ecpp.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for C +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ejava.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ejava.html new file mode 100644 index 0000000..6e9e2b3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ejava.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Ejava + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Ejava
    In: + + erubis/engine/ejava.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for Java +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ejavascript.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ejavascript.html new file mode 100644 index 0000000..e065ab6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ejavascript.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Ejavascript + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Ejavascript
    In: + + erubis/engine/ejavascript.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for JavaScript +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Engine.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Engine.html new file mode 100644 index 0000000..3d340e4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Engine.html @@ -0,0 +1,305 @@ + + + + + + Class: Erubis::Engine + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Engine
    In: + + erubis/engine.rb + +
    +
    Parent: + Object +
    +
    + + +
    + + + +
    + +
    +

    +(abstract) abstract engine class. subclass must include evaluator and +converter module. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + convert!   + load_file   + new   + process   + process_proc   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    +load file, write cache file, and return engine object. this method create +code cache file automatically. cachefile name can be specified with +properties[:cachename], or filname + ‘cache’ is used as +default. +

    +

    [Source]

    +
    +
    +# File erubis/engine.rb, line 48
    +    def self.load_file(filename, properties={})
    +      cachename = properties[:cachename] || (filename + '.cache')
    +      properties[:filename] = filename
    +      timestamp = File.mtime(filename)
    +      if test(?f, cachename) && timestamp == File.mtime(cachename)
    +        engine = self.new(nil, properties)
    +        engine.src = File.read(cachename)
    +      else
    +        input = File.open(filename, 'rb') {|f| f.read }
    +        engine = self.new(input, properties)
    +        tmpname = cachename + rand().to_s[1,8]
    +        File.open(tmpname, 'wb') {|f| f.write(engine.src) }
    +        File.rename(tmpname, cachename)
    +        File.utime(timestamp, timestamp, cachename)
    +      end
    +      engine.src.untaint   # ok?
    +      return engine
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +include Evaluator include Converter include Generator +

    +

    [Source]

    +
    +
    +# File erubis/engine.rb, line 25
    +    def initialize(input=nil, properties={})
    +      #@input = input
    +      init_generator(properties)
    +      init_converter(properties)
    +      init_evaluator(properties)
    +      @src    = convert(input) if input
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    +convert input string and set it to @src +

    +

    [Source]

    +
    +
    +# File erubis/engine.rb, line 37
    +    def convert!(input)
    +      @src = convert(input)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +helper method to convert and evaluate input text with context object. +context may be Binding, Hash, or Object. +

    +

    [Source]

    +
    +
    +# File erubis/engine.rb, line 72
    +    def process(input, context=nil, filename=nil)
    +      code = convert(input)
    +      filename ||= '(erubis)'
    +      if context.is_a?(Binding)
    +        return eval(code, context, filename)
    +      else
    +        context = Context.new(context) if context.is_a?(Hash)
    +        return context.instance_eval(code, filename)
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +helper method evaluate Proc object with contect object. context may be +Binding, Hash, or Object. +

    +

    [Source]

    +
    +
    +# File erubis/engine.rb, line 88
    +    def process_proc(proc_obj, context=nil, filename=nil)
    +      if context.is_a?(Binding)
    +        filename ||= '(erubis)'
    +        return eval(proc_obj, context, filename)
    +      else
    +        context = Context.new(context) if context.is_a?(Hash)
    +        return context.instance_eval(&proc_obj)
    +      end
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Eperl.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Eperl.html new file mode 100644 index 0000000..60c491c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Eperl.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Eperl + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Eperl
    In: + + erubis/engine/eperl.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for Perl +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ephp.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ephp.html new file mode 100644 index 0000000..8486dd6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Ephp.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Ephp + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Ephp
    In: + + erubis/engine/ephp.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for PHP +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErboutEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErboutEnhancer.html new file mode 100644 index 0000000..ecc18b0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErboutEnhancer.html @@ -0,0 +1,175 @@ + + + + + + Module: Erubis::ErboutEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::ErboutEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +set buffer variable name to ‘_erbout’ as well as +‘_buf‘ +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_postamble   + add_preamble   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 260
    +    def add_postamble(src)
    +      src << "\n" unless src[-1] == ?\n
    +      src << "#{@bufvar}.to_s\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 256
    +    def add_preamble(src)
    +      src << "_erbout = #{@bufvar} = '';"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErboutEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErboutEruby.html new file mode 100644 index 0000000..662e9f1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErboutEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::ErboutEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::ErboutEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErubisError.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErubisError.html new file mode 100644 index 0000000..5e7732b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/ErubisError.html @@ -0,0 +1,117 @@ + + + + + + Class: Erubis::ErubisError + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::ErubisError
    In: + + erubis/error.rb + +
    +
    Parent: + StandardError +
    +
    + + +
    + + + +
    + +
    +

    +base error class +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Eruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Eruby.html new file mode 100644 index 0000000..c5da50d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Eruby.html @@ -0,0 +1,132 @@ + + + + + + Class: Erubis::Eruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Eruby
    In: + + erubis/engine/eruby.rb + +
    + + erubis/helpers/rails_helper.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for Ruby +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapeEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapeEnhancer.html new file mode 100644 index 0000000..d32b56d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapeEnhancer.html @@ -0,0 +1,165 @@ + + + + + + Module: Erubis::EscapeEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::EscapeEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +switch ’<%= … %>’ to escaped and ’<%== +… %>’ to unescaped +

    +

    +ex. +

    +
    +  class XmlEruby < Eruby
    +    include EscapeEnhancer
    +  end
    +
    +

    +this is language-indenedent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_expr   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 37
    +    def add_expr(src, code, indicator)
    +      case indicator
    +      when '='
    +        @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
    +      when '=='
    +        @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
    +      when '==='
    +        add_expr_debug(src, code)
    +      end
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEc.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEc.html new file mode 100644 index 0000000..b83d688 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEc.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEc + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEc
    In: + + erubis/engine/ec.rb + +
    +
    Parent: + + Ec + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEcpp.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEcpp.html new file mode 100644 index 0000000..d7065b6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEcpp.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEcpp + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEcpp
    In: + + erubis/engine/ecpp.rb + +
    +
    Parent: + + Ecpp + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEjava.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEjava.html new file mode 100644 index 0000000..1a59c7e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEjava.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEjava + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEjava
    In: + + erubis/engine/ejava.rb + +
    +
    Parent: + + Ejava + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEjavascript.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEjavascript.html new file mode 100644 index 0000000..d376314 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEjavascript.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEjavascript + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEjavascript
    In: + + erubis/engine/ejavascript.rb + +
    +
    Parent: + + Ejavascript + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEperl.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEperl.html new file mode 100644 index 0000000..10bdb71 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEperl.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEperl + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEperl
    In: + + erubis/engine/eperl.rb + +
    +
    Parent: + + Eperl + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEphp.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEphp.html new file mode 100644 index 0000000..e58b86d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEphp.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEphp + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEphp
    In: + + erubis/engine/ephp.rb + +
    +
    Parent: + + Ephp + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEruby.html new file mode 100644 index 0000000..f9362d6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEruby.html @@ -0,0 +1,127 @@ + + + + + + Class: Erubis::EscapedEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEruby
    In: + + erubis/engine/eruby.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + +
    +

    +swtich ’<%= %>’ to escaped and ’<%== +%>’ to not escaped +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEscheme.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEscheme.html new file mode 100644 index 0000000..8c5e970 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/EscapedEscheme.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::EscapedEscheme + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::EscapedEscheme
    In: + + erubis/engine/escheme.rb + +
    +
    Parent: + + Escheme + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Escheme.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Escheme.html new file mode 100644 index 0000000..53424ba --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Escheme.html @@ -0,0 +1,126 @@ + + + + + + Class: Erubis::Escheme + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Escheme
    In: + + erubis/engine/escheme.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +engine for Scheme +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Evaluator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Evaluator.html new file mode 100644 index 0000000..76696e2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Evaluator.html @@ -0,0 +1,212 @@ + + + + + + Module: Erubis::Evaluator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Evaluator
    In: + + erubis/evaluator.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +evaluate code +

    + +
    + + +
    + +
    +

    Methods

    + +
    + evaluate   + init_evaluator   + result   +
    +
    + +
    + + + + +
    + + + + + +
    +

    Attributes

    + +
    + + + + + + + + + + + +
    filename [RW] 
    src [RW] 
    +
    +
    + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/evaluator.rb, line 34
    +    def evaluate(*args)
    +      raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/evaluator.rb, line 26
    +    def init_evaluator(properties)
    +      @filename = properties[:filename]
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/evaluator.rb, line 30
    +    def result(*args)
    +      raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/FastEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/FastEruby.html new file mode 100644 index 0000000..2585291 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/FastEruby.html @@ -0,0 +1,131 @@ + + + + + + Class: Erubis::FastEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::FastEruby
    In: + + erubis/engine/eruby.rb + +
    + + erubis/helpers/rails_helper.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + +
    +

    +fast engine for Ruby +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Generator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Generator.html new file mode 100644 index 0000000..e645550 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Generator.html @@ -0,0 +1,416 @@ + + + + + + Module: Erubis::Generator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Generator
    In: + + erubis/generator.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +code generator, called by Converter module +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + + +
    + + + + + +
    +

    Attributes

    + +
    + + + + + + +
    escapefunc [RW] 
    +
    +
    + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    +(abstract) add expression code to src for debug. this is called by +add_expr(). +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 72
    +    def add_expr_debug(src, code)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) add escaped expression code to src. this is called by +add_expr(). +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 67
    +    def add_expr_escaped(src, code)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) add expression literal code to src. this is called by +add_expr(). +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 62
    +    def add_expr_literal(src, code)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) add @postamble to src +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 77
    +    def add_postamble(src)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) add @preamble to src +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 47
    +    def add_preamble(src)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) add statement code to src +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 57
    +    def add_stmt(src, code)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) add text string to src +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 52
    +    def add_text(src, text)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +(abstract) escape text string +

    +

    +ex. +

    +
    +  def escape_text(text)
    +    return text.dump
    +    # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
    +  end
    +
    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 36
    +    def escape_text(text)
    +      not_implemented
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +return escaped expression code (ex. ‘h(…)’ or +‘htmlspecialchars(…)’) +

    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 41
    +    def escaped_expr(code)
    +      code.strip!
    +      return "#{@escapefunc}(#{code})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/generator.rb, line 24
    +    def init_generator(properties={})
    +      @escapefunc = properties[:escapefunc]
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/HeaderFooterEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/HeaderFooterEnhancer.html new file mode 100644 index 0000000..faf13ae --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/HeaderFooterEnhancer.html @@ -0,0 +1,267 @@ + + + + + + Module: Erubis::HeaderFooterEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::HeaderFooterEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +
    +
    experimental
    allow header and footer in eRuby script + +
    +
    +

    +ex. +

    +
    +  ====================
    +  ## without header and footer
    +  $ cat ex1.eruby
    +  <% def list_items(list) %>
    +  <%   for item in list %>
    +  <li><%= item %></li>
    +  <%   end %>
    +  <% end %>
    +
    +  $ erubis -s ex1.eruby
    +  _buf = []; def list_items(list)
    +  ;   for item in list
    +  ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
    +  ';   end
    +  ; end
    +  ;
    +  _buf.join
    +
    +  ## with header and footer
    +  $ cat ex2.eruby
    +  <!--#header:
    +  def list_items(list)
    +   #-->
    +  <%  for item in list %>
    +  <li><%= item %></li>
    +  <%  end %>
    +  <!--#footer:
    +  end
    +   #-->
    +
    +  $ erubis -s -c HeaderFooterEruby ex4.eruby
    +
    +  def list_items(list)
    +   _buf = []; _buf << '
    +  ';  for item in list
    +  ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
    +  ';  end
    +  ; _buf << '
    +  ';
    +  _buf.join
    +  end
    +
    +  ====================
    +
    +

    +this is language-independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_text   + convert   +
    +
    + +
    + + + + +
    + + +
    +

    Constants

    + +
    + + + + + + +
    HEADER_FOOTER_PATTERN=/(.*?)(^[ \t]*)?<!--\#(\w+):(.*?)\#-->([ \t]*\r?\n)?/m
    +
    +
    + + + +
    +

    Attributes

    + +
    + + + + + + + + + + + +
    footer [RW] 
    header [RW] 
    +
    +
    + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 585
    +    def add_text(src, text)
    +      m = nil
    +      text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace|
    +        m = Regexp.last_match
    +        flag_trim = @trim && lspace && rspace
    +        super(src, txt)
    +        content = "#{lspace}#{content}#{rspace}" if flag_trim
    +        super(src, lspace) if !flag_trim && lspace
    +        instance_variable_set("@#{word}", content)
    +        super(src, rspace) if !flag_trim && rspace
    +      end
    +      #rest = $' || text                    # ruby1.8
    +      rest = m ? text[m.end(0)..-1] : text  # ruby1.9
    +      super(src, rest)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 603
    +    def convert(input)
    +      source = super
    +      return @src = "#{@header}#{source}#{@footer}"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/HeaderFooterEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/HeaderFooterEruby.html new file mode 100644 index 0000000..465ac8b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/HeaderFooterEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::HeaderFooterEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::HeaderFooterEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers.html new file mode 100644 index 0000000..8079c6b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers.html @@ -0,0 +1,116 @@ + + + + + + Module: Erubis::Helpers + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Helpers
    In: + + erubis/helpers/rails_form_helper.rb + +
    + + erubis/helpers/rails_helper.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + + +
    + +
    +

    Classes and Modules

    + + Module Erubis::Helpers::RailsFormHelper
    +Module Erubis::Helpers::RailsHelper
    + +
    + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsFormHelper.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsFormHelper.html new file mode 100644 index 0000000..a282eb1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsFormHelper.html @@ -0,0 +1,787 @@ + + + + + + Module: Erubis::Helpers::RailsFormHelper + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Helpers::RailsFormHelper
    In: + + erubis/helpers/rails_form_helper.rb + +
    +
    +
    + + + + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 106
    +  def _pp_check_box_checked?(value, checked_value)
    +    return ActionView::Helpers::InstanceTag::check_box_checked?(value, checked_value)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 46
    +  def _pp_error_tags(value)
    +    return value ? ['<div class="fieldWithErrors">', '</div>'] : ['', '']
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 117
    +  def _pp_radio_button_checked?(value, tag_value)
    +    return ActionView::Helpers::InstanceTag::radio_button_checked?(value, tag_value)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 50
    +  def _pp_remove_error_div(s)
    +    s.sub!(/\A<div class="fieldWithErrors">(.*)<\/div>\z/, '\1')
    +    return s
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 121
    +  def _pp_select(object, method, collection, priority_collection, options={}, html_options={})
    +    return pp_error_on(object, method) do
    +      s = ""
    +      ## start tag
    +      s << "<select id=\"#{object}_#{method}\" name=\"#{object}[#{method}]\""
    +      for key, val in html_options:
    +          s << " #{key}=\"#{val}\""
    +      end
    +      s << ">\n"
    +      ## selected table
    +      key = options.key?(:value) ? :value : (options.key?('value') ? 'value' : nil)
    +      if    key.nil?                ;  selected = "@#{object}.#{method}"
    +      elsif (val=options[key]).nil? ;  selected = nil
    +      elsif val =~ /\A<%=(.*)%>\z/  ;  selected = $1
    +      else                          ;  selected = val.inspect
    +      end
    +      s << "<% _table = {#{selected}=>' selected=\"selected\"'} %>\n" if selected
    +      ## <option> tags
    +      if options[:include_blank] || options['include_blank']
    +        s << "<option value=\"\"></option>\n"
    +      end
    +      unless priority_collection.blank?
    +        _pp_select_options(s, priority_collection, selected, 'delete')
    +        s << "<option value=\"\">-------------</option>\n"
    +      end
    +      _pp_select_options(s, collection, selected, '[]')
    +      ## end tag
    +      s << "</select>"
    +      s
    +    end
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 153
    +  def _pp_select_options(s, collection, selected, operator)
    +    for item in collection
    +      value, text = item.is_a?(Array) ? item : [item, item]
    +      if !selected
    +        t = ''
    +      elsif operator == 'delete'
    +        t = "<%= _table.delete(#{value.inspect}) %>"
    +      else
    +        t = "<%= _table[#{value.inspect}] %>"
    +      end
    +      s << "<option value=\"#{h value}\"#{t}>#{h text}</option>\n"
    +    end
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 99
    +  def pp_check_box(object_name, method, options={}, checked_value="1", unchecked_value="0")
    +    s = check_box(object_name, method, options, checked_value, unchecked_value)
    +    s.sub!(/\schecked=\"checked\"/, '')
    +    s.sub!(/type="checkbox"/, "\\&<%= _pp_check_box_checked?(@#{object_name}.#{method}, #{checked_value.inspect}) ? ' checked=\"checked\"' : '' %>")
    +    return pp_error_on(object_name, method) { _pp_remove_error_div(s) }
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 171
    +  def pp_collection_select(object, method, collection, value_method, text_method, options={}, html_options={})
    +    collection2 = collection.collect { |e|
    +      [e.__send__(value_method), e.__send__(text_method)]
    +    }
    +    return _pp_select(object, method, collection2, nil, options, html_options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 178
    +  def pp_country_select(object, method, priority_countries=nil, options={}, html_options={})
    +    collection = ActionView::Helpers::FormOptionsHelper::COUNTRIES
    +    return _pp_select(object, method, collection, priority_countries, options, html_options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 37
    +  def pp_error_on(object_name, method)
    +    s = ''
    +    s << "<% _stag, _etag = _pp_error_tags(@#{object_name}.errors.on('#{method}')) %>"
    +    s << "<%= _stag %>"
    +    s << yield(object_name, method)
    +    s << "<%= _etag %>"
    +    return s
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 91
    +  def pp_file_field(object_name, method, options={})
    +    return pp_tag_helper(:file_field, object_name, method, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 69
    +  def pp_form_tag(url_for_options={}, options={}, *parameters_for_url, &block)
    +    return form_tag(url_for_options, options, *parameters_for_url, &block)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 87
    +  def pp_hidden_field(object_name, method, options={})
    +    return pp_tag_helper(:hidden_field, object_name, method, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 193
    +  def pp_image_submit_tag(source, options={})
    +    return image_submit_tag(source, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 83
    +  def pp_password_field(object_name, method, options={})
    +    return pp_tag_helper(:password_field, object_name, method, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 110
    +  def pp_radio_button(object_name, method, tag_value, options={})
    +    s = radio_button(object_name, method, tag_value, options)
    +    s.sub!(/\schecked=\"checked\"/, '')
    +    s.sub!(/type="radio"/, "\\&<%= _pp_radio_button_checked?(@#{object_name}.#{method}, #{tag_value.inspect}) ? ' checked=\"checked\"' : '' %>")
    +    return pp_error_on(object_name, method) { _pp_remove_error_div(s) }
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 30
    +  def pp_render_partial(basename)
    +    basename = "_#{basename}" unless basename[0] == ?_
    +    filename = pp_template_filename(basename)
    +    preprocessor = _create_preprocessor(File.read(filename))
    +    return preprocessor.evaluate(_preprocessing_context_object())
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 167
    +  def pp_select(object, method, collection, options={}, html_options={})
    +    return _pp_select(object, method, collection, nil, options, html_options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 189
    +  def pp_submit_tag(value="Save changes", options={})
    +    return submit_tag(value, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 55
    +  def pp_tag_helper(helper, object_name, method, options={})
    +    if object_name.is_a?(ActionView::Helpers::FormHelper)
    +      object_name = object_name.object_name
    +    end
    +    unless options.key?(:value) || options.key?('value')
    +      options['value'] = _?("h @#{object_name}.#{method}")
    +    end
    +    #$stderr.puts "*** debug: pp_tag_helper(): options=#{options.inspect}"
    +    return pp_error_on(object_name, method) {
    +      s = __send__(helper, object_name, method, options)
    +      _pp_remove_error_div(s)
    +    }
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 23
    +  def pp_template_filename(basename)
    +    fname = "#{RAILS_ROOT}/app/views/#{controller.controller_name}/#{basename}.html.erb"
    +    return fname if test(?f, fname)
    +    return  "#{RAILS_ROOT}/app/views/#{controller.controller_name}/#{basename}.rhtml"
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 19
    +  def pp_template_filename(basename)
    +    return "#{RAILS_ROOT}/app/views/#{controller.controller_name}/#{basename}.rhtml"
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 95
    +  def pp_text_area(object_name, method, options={})
    +    return pp_tag_helper(:text_area, object_name, method, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 79
    +  def pp_text_field(object_name, method, options={})
    +    return pp_tag_helper(:text_field, object_name, method, options)
    +  end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_form_helper.rb, line 183
    +  def pp_time_zone_select(object, method, priority_zones=nil, options={}, html_options={})
    +    model = options[:model] || options['model'] || TimeZone
    +    collection = model.all.collect { |e| [e.name, e.to_s] }
    +    return _pp_select(object, method, collection, priority_zones, options, html_options)
    +  end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsHelper.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsHelper.html new file mode 100644 index 0000000..e1829c1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsHelper.html @@ -0,0 +1,349 @@ + + + + + + Module: Erubis::Helpers::RailsHelper + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Helpers::RailsHelper
    In: + + erubis/helpers/rails_helper.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +helper module for Ruby on Rails +

    +

    +howto: +

    +
      +
    1. add the folliwng code in your ‘config/environment.rb‘ + +
      +  require 'erubis/helpers/rails_helper'
      +  #Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby # or Erubis::FastEruby
      +  #Erubis::Helpers::RailsHelper.init_properties = {}
      +  #Erubis::Helpers::RailsHelper.show_src = false       # set true for debugging
      +  #Erubis::Helpers::RailsHelper.preprocessing = true   # set true to enable preprocessing
      +
      +
    2. +
    3. restart web server. + +
    4. +
    +

    +if Erubis::Helper::Rails.show_src is true, Erubis prints converted Ruby code into log +file (‘log/development.log’ or so). if false, it doesn‘t. +if nil, Erubis prints converted Ruby code +if ENV[‘RAILS_ENV’] == ‘development’. +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + + +
    + +
    +

    Classes and Modules

    + + Module Erubis::Helpers::RailsHelper::TemplateConverter
    + +
    + + + + + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    +@@engine_class = ::Erubis::FastEruby +

    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 47
    +      def self.engine_class
    +        @@engine_class
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 50
    +      def self.engine_class=(klass)
    +        @@engine_class = klass
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 56
    +      def self.init_properties
    +        @@init_properties
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 59
    +      def self.init_properties=(hash)
    +        @@init_properties = hash
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 74
    +      def self.preprocessing
    +        @@preprocessing
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 77
    +      def self.preprocessing=(flag)
    +        @@preprocessing = flag
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 65
    +      def self.show_src
    +        @@show_src
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 68
    +      def self.show_src=(flag)
    +        @@show_src = flag
    +      end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsHelper/TemplateConverter.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsHelper/TemplateConverter.html new file mode 100644 index 0000000..0256059 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Helpers/RailsHelper/TemplateConverter.html @@ -0,0 +1,213 @@ + + + + + + Module: Erubis::Helpers::RailsHelper::TemplateConverter + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::Helpers::RailsHelper::TemplateConverter
    In: + + erubis/helpers/rails_helper.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + + + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 107
    +        def _create_preprocessor(template)
    +          return PreprocessingEruby.new(template, :escape=>true)
    +        end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 113
    +        def _logger_info(message)
    +          logger.info message
    +        end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 164
    +      def _logger_info(message)
    +        #logger.info message   # logger.info seems not available in Rails 2.2
    +        ActionController::Base.new.logger.info message
    +      end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helpers/rails_helper.rb, line 110
    +        def _preprocessing_context_object
    +          return self
    +        end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/InterpolationEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/InterpolationEnhancer.html new file mode 100644 index 0000000..877de9b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/InterpolationEnhancer.html @@ -0,0 +1,305 @@ + + + + + + Module: Erubis::InterpolationEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::InterpolationEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +convert "<h1><%=title%></h1>" into "_buf +<< %Q`<h1>#{title}</h1>`" +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 707
    +    def _add_text_to_str(str, text)
    +      return if !text || text.empty?
    +      str << text.gsub(/[`\#\\]/, '\\\\\&')
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 712
    +    def add_expr_escaped(str, code)
    +      str << "\#{#{escaped_expr(code)}}"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 716
    +    def add_expr_literal(str, code)
    +      str << "\#{#{code}}"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 696
    +    def add_text(src, text)
    +      return if !text || text.empty?
    +      #src << " _buf << %Q`" << text << "`;"
    +      if text[-1] == ?\n
    +        text[-1] = "\\n"
    +        src << " #{@bufvar} << %Q`#{text}`\n"
    +      else
    +        src << " #{@bufvar} << %Q`#{text}`;"
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 641
    +    def convert_input(src, input)
    +      pat = @pattern
    +      regexp = pat.nil? || pat == '<% %>' ? Basic::Converter::DEFAULT_REGEXP : pattern_regexp(pat)
    +      pos = 0
    +      is_bol = true     # is beginning of line
    +      str = ''
    +      input.scan(regexp) do |indicator, code, tailch, rspace|
    +        match = Regexp.last_match()
    +        len  = match.begin(0) - pos
    +        text = input[pos, len]
    +        pos  = match.end(0)
    +        ch   = indicator ? indicator[0] : nil
    +        lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
    +        is_bol = rspace ? true : false
    +        _add_text_to_str(str, text)
    +        ## * when '<%= %>', do nothing
    +        ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
    +        if ch == ?=              # <%= %>
    +          rspace = nil if tailch && !tailch.empty?
    +          str << lspace if lspace
    +          add_expr(str, code, indicator)
    +          str << rspace if rspace
    +        elsif ch == ?\#          # <%# %>
    +          n = code.count("\n") + (rspace ? 1 : 0)
    +          if @trim && lspace && rspace
    +            add_text(src, str)
    +            str = ''
    +            add_stmt(src, "\n" * n)
    +          else
    +            str << lspace if lspace
    +            add_text(src, str)
    +            str = ''
    +            add_stmt(src, "\n" * n)
    +            str << rspace if rspace
    +          end
    +        else                     # <% %>
    +          if @trim && lspace && rspace
    +            add_text(src, str)
    +            str = ''
    +            add_stmt(src, "#{lspace}#{code}#{rspace}")
    +          else
    +            str << lspace if lspace
    +            add_text(src, str)
    +            str = ''
    +            add_stmt(src, code)
    +            str << rspace if rspace
    +          end
    +        end
    +      end
    +      #rest = $' || input                       # ruby1.8
    +      rest = pos == 0 ? input : input[pos..-1]  # ruby1.9
    +      _add_text_to_str(str, rest)
    +      add_text(src, str)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/InterpolationEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/InterpolationEruby.html new file mode 100644 index 0000000..8716d80 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/InterpolationEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::InterpolationEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::InterpolationEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/JavaGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/JavaGenerator.html new file mode 100644 index 0000000..29db5b8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/JavaGenerator.html @@ -0,0 +1,359 @@ + + + + + + Module: Erubis::JavaGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::JavaGenerator
    In: + + erubis/engine/ejava.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 68
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      src << " System.err.println(\"*** debug: #{code}=\"+(#{code}));"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 64
    +    def add_expr_escaped(src, code)
    +      add_expr_literal(src, escaped_expr(code))
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 58
    +    def add_expr_literal(src, code)
    +      src << @indent if src.empty? || src[-1] == ?\n
    +      code.strip!
    +      src << " #{@bufvar}.append(#{code});"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 74
    +    def add_postamble(src)
    +      src << "\n" if src[-1] == ?;
    +      src << @indent << "return " << @bufvar << ".toString();\n"
    +      #src << @indent << "System.out.print(" << @bufvar << ".toString());\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 32
    +    def add_preamble(src)
    +      src << "#{@indent}#{@bufclass} #{@bufvar} = new #{@bufclass}();"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 54
    +    def add_stmt(src, code)
    +      src << code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 41
    +    def add_text(src, text)
    +      return if text.empty?
    +      src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
    +      src << @bufvar << ".append("
    +      i = 0
    +      text.each_line do |line|
    +        src << "\n" << @indent << '          + ' if i > 0
    +        i += 1
    +        src << '"' << escape_text(line) << '"'
    +      end
    +      src << ");" << (text[-1] == ?\n ? "\n" : "")
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 36
    +    def escape_text(text)
    +      @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
    +      return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 24
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= 'escape'
    +      @indent = properties[:indent] || ''
    +      @bufvar = properties[:bufvar] || '_buf'
    +      @bufclass = properties[:bufclass] || 'StringBuffer'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/JavascriptGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/JavascriptGenerator.html new file mode 100644 index 0000000..5ec28da --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/JavascriptGenerator.html @@ -0,0 +1,386 @@ + + + + + + Module: Erubis::JavascriptGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::JavascriptGenerator
    In: + + erubis/engine/ejavascript.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 72
    +    def add_expr_debug(src, code)
    +      add_indent(src, @indent)
    +      code.strip!
    +      src << "alert(\"*** debug: #{code}=\"+(#{code}));"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 68
    +    def add_expr_escaped(src, code)
    +      add_expr_literal(src, escaped_expr(code))
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 62
    +    def add_expr_literal(src, code)
    +      add_indent(src, @indent)
    +      code.strip!
    +      src << "#{@bufvar}.push(#{code});"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 41
    +    def add_indent(src, indent)
    +      src << (src.empty? || src[-1] == ?\n ? indent : ' ')
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 78
    +    def add_postamble(src)
    +      src << "\n" if src[-1] == ?;
    +      if @docwrite
    +        src << @indent << 'document.write(' << @bufvar << ".join(\"\"));\n"
    +      else
    +        src << @indent << @bufvar << ".join(\"\");\n"
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 32
    +    def add_preamble(src)
    +      src << "#{@indent}var #{@bufvar} = [];"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 58
    +    def add_stmt(src, code)
    +      src << code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 45
    +    def add_text(src, text)
    +      return if text.empty?
    +      add_indent(src, @indent)
    +      src << @bufvar << '.push("'
    +      s = escape_text(text)
    +      if s[-1] == ?\n
    +        s[-2, 2] = ''
    +        src << s << "\");\n"
    +      else
    +        src << s << "\");"
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 36
    +    def escape_text(text)
    +      @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n\\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
    +      return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 24
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= 'escape'
    +      @indent = properties[:indent] || ''
    +      @bufvar = properties[:bufvar] || '_buf'
    +      @docwrite = properties[:docwrite] != false  # '!= false' will be removed in the next release
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Main.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Main.html new file mode 100644 index 0000000..8a14c5d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/Main.html @@ -0,0 +1,341 @@ + + + + + + Class: Erubis::Main + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::Main
    In: + + erubis/main.rb + +
    +
    Parent: + Object +
    +
    + + +
    + + + +
    + +
    +

    +main class of command +

    +

    +ex. +

    +
    +  Main.main(ARGV)
    +
    + +
    + + +
    + +
    +

    Methods

    + +
    + execute   + main   + new   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/main.rb, line 40
    +    def self.main(argv=ARGV)
    +      status = 0
    +      begin
    +        Main.new.execute(ARGV)
    +      rescue CommandOptionError => ex
    +        $stderr.puts ex.message
    +        status = 1
    +      end
    +      exit(status)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/main.rb, line 51
    +    def initialize
    +      @single_options = "hvxztTSbeBXNUC"
    +      @arg_options    = "pcrfKIlaE" #C
    +      @option_names   = {
    +        'h' => :help,
    +        'v' => :version,
    +        'x' => :source,
    +        'z' => :syntax,
    +        'T' => :unexpand,
    +        't' => :untabify,      # obsolete
    +        'S' => :intern,
    +        'b' => :bodyonly,
    +        'B' => :binding,
    +        'p' => :pattern,
    +        'c' => :context,
    +        #'C' => :class,
    +        'e' => :escape,
    +        'r' => :requires,
    +        'f' => :datafiles,
    +        'K' => :kanji,
    +        'I' => :includes,
    +        'l' => :lang,
    +        'a' => :action,
    +        'E' => :enhancers,
    +        'X' => :notext,
    +        'N' => :linenum,
    +        'U' => :unique,
    +        'C' => :compact,
    +      }
    +      assert unless @single_options.length + @arg_options.length == @option_names.length
    +      (@single_options + @arg_options).each_byte do |ch|
    +        assert unless @option_names.key?(ch.chr)
    +      end
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/main.rb, line 87
    +    def execute(argv=ARGV)
    +      ## parse command-line options
    +      options, properties = parse_argv(argv, @single_options, @arg_options)
    +      filenames = argv
    +      options['h'] = true if properties[:help]
    +      opts = Object.new
    +      arr = @option_names.collect {|ch, name| "def #{name}; @#{name}; end\n" }
    +      opts.instance_eval arr.join
    +      options.each do |ch, val|
    +        name = @option_names[ch]
    +        opts.instance_variable_set("@#{name}", val)
    +      end
    +
    +      ## help, version, enhancer list
    +      if opts.help || opts.version
    +        puts version()         if opts.version
    +        puts usage()           if opts.help
    +        puts show_properties() if opts.help
    +        puts show_enhancers()  if opts.help
    +        return
    +      end
    +
    +      ## include path
    +      opts.includes.split(/,/).each do |path|
    +        $: << path
    +      end if opts.includes
    +
    +      ## require library
    +      opts.requires.split(/,/).each do |library|
    +        require library
    +      end if opts.requires
    +
    +      ## action
    +      action = opts.action
    +      action ||= 'syntax'  if opts.syntax
    +      action ||= 'convert' if opts.source || opts.notext
    +
    +      ## lang
    +      lang = opts.lang || 'ruby'
    +      action ||= 'convert' if opts.lang
    +
    +      ## class name of Eruby
    +      #classname = opts.class
    +      classname = nil
    +      klass = get_classobj(classname, lang, properties[:pi])
    +
    +      ## kanji code
    +      $KCODE = opts.kanji if opts.kanji
    +
    +      ## read context values from yaml file
    +      datafiles = opts.datafiles
    +      context = load_datafiles(datafiles, opts)
    +
    +      ## parse context data
    +      if opts.context
    +        context = parse_context_data(opts.context, opts)
    +      end
    +
    +      ## properties for engine
    +      properties[:escape]   = true         if opts.escape && !properties.key?(:escape)
    +      properties[:pattern]  = opts.pattern if opts.pattern
    +      #properties[:trim]     = false        if opts.notrim
    +      properties[:preamble] = properties[:postamble] = false if opts.bodyonly
    +      properties[:pi]       = nil          if properties[:pi] == true
    +
    +      ## create engine and extend enhancers
    +      engine = klass.new(nil, properties)
    +      enhancers = get_enhancers(opts.enhancers)
    +      #enhancers.push(Erubis::EscapeEnhancer) if opts.escape
    +      enhancers.each do |enhancer|
    +        engine.extend(enhancer)
    +        engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
    +      end
    +
    +      ## no-text
    +      engine.extend(Erubis::NoTextEnhancer) if opts.notext
    +
    +      ## convert and execute
    +      val = nil
    +      msg = "Syntax OK\n"
    +      if filenames && !filenames.empty?
    +        filenames.each do |filename|
    +          File.file?(filename)  or
    +            raise CommandOptionError.new("#{filename}: file not found.")
    +          engine.filename = filename
    +          engine.convert!(File.read(filename))
    +          val = do_action(action, engine, context, filename, opts)
    +          msg = nil if val
    +        end
    +      else
    +        engine.filename = filename = '(stdin)'
    +        engine.convert!($stdin.read())
    +        val = do_action(action, engine, context, filename, opts)
    +        msg = nil if val
    +      end
    +      print msg if action == 'syntax' && msg
    +
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoCodeEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoCodeEnhancer.html new file mode 100644 index 0000000..25765a0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoCodeEnhancer.html @@ -0,0 +1,249 @@ + + + + + + Module: Erubis::NoCodeEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::NoCodeEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +remove code and leave text, especially useful when validating HTML tags. +

    +

    +ex. +

    +
    +  $ erubis -s -E NoCode file.eruby | tidy -errors
    +
    +

    +this is language independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_expr   + add_postamble   + add_preamble   + add_stmt   + add_text   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 317
    +    def add_expr(src, code, indicator)
    +      src << "\n" * code.count("\n")
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 310
    +    def add_postamble(src)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 307
    +    def add_preamble(src)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 321
    +    def add_stmt(src, code)
    +      src << "\n" * code.count("\n")
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 313
    +    def add_text(src, text)
    +      src << text
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoCodeEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoCodeEruby.html new file mode 100644 index 0000000..f52b4d0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoCodeEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::NoCodeEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::NoCodeEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoTextEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoTextEnhancer.html new file mode 100644 index 0000000..feaf9d6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoTextEnhancer.html @@ -0,0 +1,159 @@ + + + + + + Module: Erubis::NoTextEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::NoTextEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +remove text and leave code, especially useful when debugging. +

    +

    +ex. +

    +
    +  $ erubis -s -E NoText file.eruby | more
    +
    +

    +this is language independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_text   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 282
    +    def add_text(src, text)
    +      src << ("\n" * text.count("\n"))
    +      if text[-1] != ?\n
    +        text =~ /^(.*?)\z/
    +        src << (' ' * $1.length)
    +      end
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoTextEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoTextEruby.html new file mode 100644 index 0000000..c6094c0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NoTextEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::NoTextEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::NoTextEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NotSupportedError.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NotSupportedError.html new file mode 100644 index 0000000..c3c75b7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/NotSupportedError.html @@ -0,0 +1,119 @@ + + + + + + Class: Erubis::NotSupportedError + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::NotSupportedError
    In: + + erubis/error.rb + +
    +
    Parent: + + ErubisError + +
    +
    + + +
    + + + +
    + +
    +

    +raised when method or function is not supported +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedEruby.html new file mode 100644 index 0000000..6bb2640 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedEruby.html @@ -0,0 +1,163 @@ + + + + + + Class: Erubis::OptimizedEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::OptimizedEruby
    In: + + erubis/engine/optimized.rb + +
    +
    Parent: + + Basic::Engine + +
    +
    + + +
    + + + +
    + +
    +

    +Eruby class which generates optimized ruby code +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 106
    +    def init_converter(properties={})
    +      @pi = 'rb'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedGenerator.html new file mode 100644 index 0000000..2021490 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedGenerator.html @@ -0,0 +1,439 @@ + + + + + + Module: Erubis::OptimizedGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::OptimizedGenerator
    In: + + erubis/engine/optimized.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 20
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= "Erubis::XmlHelper.escape_xml"
    +      @initialized = false
    +      @prev_is_expr = false
    +    end
    +
    +
    +
    +
    + +

    Protected Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 85
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      s = (code.dump =~ /\A"(.*)"\z/) && $1
    +      src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 79
    +    def add_expr_escaped(src, code)
    +      unless @initialized; src << "_buf = ''"; @initialized = true; end
    +      switch_to_expr(src)
    +      src << " << " << escaped_expr(code)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 73
    +    def add_expr_literal(src, code)
    +      unless @initialized; src << "_buf = ''"; @initialized = true; end
    +      switch_to_expr(src)
    +      src << " << (" << code << ").to_s"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 91
    +    def add_postamble(src)
    +      #super if @initialized
    +      src << "\n_buf\n" if @initialized
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 50
    +    def add_preamble(src)
    +      #@initialized = false
    +      #@prev_is_expr = false
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 66
    +    def add_stmt(src, code)
    +      switch_to_stmt(src) if @initialized
    +      #super
    +      src << code
    +      src << ';' unless code[-1] == ?\n
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 55
    +    def add_text(src, text)
    +      return if text.empty?
    +      if @initialized
    +        switch_to_expr(src)
    +        src << " << '" << escape_text(text) << "'"
    +      else
    +        src << "_buf = '" << escape_text(text) << "';"
    +        @initialized = true
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 29
    +    def escape_text(text)
    +      text.gsub(/['\\]/, '\\\\\&')   # "'" => "\\'",  '\\' => '\\\\'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 33
    +    def escaped_expr(code)
    +      @escapefunc ||= 'Erubis::XmlHelper.escape_xml'
    +      return "#{@escapefunc}(#{code})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 38
    +    def switch_to_expr(src)
    +      return if @prev_is_expr
    +      @prev_is_expr = true
    +      src << ' _buf'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 44
    +    def switch_to_stmt(src)
    +      return unless @prev_is_expr
    +      @prev_is_expr = false
    +      src << ';'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedXmlEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedXmlEruby.html new file mode 100644 index 0000000..a7b30e1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/OptimizedXmlEruby.html @@ -0,0 +1,163 @@ + + + + + + Class: Erubis::OptimizedXmlEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::OptimizedXmlEruby
    In: + + erubis/engine/optimized.rb + +
    +
    Parent: + + OptimizedEruby + +
    +
    + + +
    + + + +
    + +
    +

    +XmlEruby class which generates optimized ruby +code +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_expr_debug   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/optimized.rb, line 120
    +    def add_expr_debug(src, code)
    +      switch_to_stmt(src) if indicator == '===' && !@initialized
    +      super
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI.html new file mode 100644 index 0000000..388ae2f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI.html @@ -0,0 +1,125 @@ + + + + + + Module: Erubis::PI + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PI
    In: + + erubis/converter.rb + +
    + + erubis/tiny.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + + +
    + + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Converter.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Converter.html new file mode 100644 index 0000000..04bec54 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Converter.html @@ -0,0 +1,266 @@ + + + + + + Module: Erubis::PI::Converter + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PI::Converter
    In: + + erubis/converter.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +Processing Instructions (PI) converter for XML. +this class converts ’<?rb … ?>’ and +’${…}’ notation. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + convert   + convert_input   + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + +
    +

    Attributes

    + +
    + + + + + + + + + + + +
    pi [RW] 
    prefix [RW] 
    +
    +
    + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 224
    +    def convert(input)
    +      code = super(input)
    +      return @header || @footer ? "#{@header}#{code}#{@footer}" : code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 215
    +    def init_converter(properties={})
    +      super(properties)
    +      @trim    = properties.fetch(:trim, true)
    +      @pi      = properties[:pi] if properties[:pi]
    +      @embchar = properties[:embchar] || '@'
    +      @pattern = properties[:pattern]
    +      @pattern = '<% %>' if @pattern.nil?  #|| @pattern == true
    +    end
    +
    +
    +
    +
    + +

    Protected Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/converter.rb, line 231
    +    def convert_input(codebuf, input)
    +      unless @regexp
    +        @pi ||= 'e'
    +        ch = Regexp.escape(@embchar)
    +        if @pattern
    +          left, right = @pattern.split(' ')
    +          @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
    +        else
    +          @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
    +        end
    +      end
    +      #
    +      is_bol = true
    +      pos = 0
    +      input.scan(@regexp) do |pi_arg, stmt, rspace,
    +                              indicator1, expr1, indicator2, expr2|
    +        match = Regexp.last_match
    +        len = match.begin(0) - pos
    +        text = input[pos, len]
    +        pos = match.end(0)
    +        lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil
    +        is_bol = stmt && rspace ? true : false
    +        add_text(codebuf, text) # unless text.empty?
    +        #
    +        if stmt
    +          if @trim && lspace && rspace
    +            add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg)
    +          else
    +            add_text(codebuf, lspace) if lspace
    +            add_pi_stmt(codebuf, stmt, pi_arg)
    +            add_text(codebuf, rspace) if rspace
    +          end
    +        else
    +          add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2)
    +        end
    +      end
    +      #rest = $' || input                        # ruby1.8
    +      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
    +      add_text(codebuf, rest)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ec.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ec.html new file mode 100644 index 0000000..bcfc83a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ec.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Ec + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Ec
    In: + + erubis/engine/ec.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEc < Ec +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ec.rb, line 109
    +    def init_converter(properties={})
    +      @pi = 'c'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ecpp.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ecpp.html new file mode 100644 index 0000000..fe85b0f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ecpp.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Ecpp + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Ecpp
    In: + + erubis/engine/ecpp.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEcpp < Ecpp +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ecpp.rb, line 105
    +    def init_converter(properties={})
    +      @pi = 'cpp'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ejava.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ejava.html new file mode 100644 index 0000000..f22cd8a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ejava.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Ejava + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Ejava
    In: + + erubis/engine/ejava.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEjava < Ejava +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejava.rb, line 103
    +    def init_converter(properties={})
    +      @pi = 'java'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ejavascript.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ejavascript.html new file mode 100644 index 0000000..f97ba7e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ejavascript.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Ejavascript + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Ejavascript
    In: + + erubis/engine/ejavascript.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEjavascript < Ejavascript +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ejavascript.rb, line 111
    +    def init_converter(properties={})
    +      @pi = 'js'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Engine.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Engine.html new file mode 100644 index 0000000..beb659a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Engine.html @@ -0,0 +1,122 @@ + + + + + + Class: Erubis::PI::Engine + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Engine
    In: + + erubis/engine.rb + +
    +
    Parent: + + Engine + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Eperl.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Eperl.html new file mode 100644 index 0000000..2fbfa6c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Eperl.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Eperl + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Eperl
    In: + + erubis/engine/eperl.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEperl < Eperl +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 87
    +    def init_converter(properties={})
    +      @pi = 'perl'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ephp.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ephp.html new file mode 100644 index 0000000..5a7ac93 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Ephp.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Ephp + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Ephp
    In: + + erubis/engine/ephp.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEphp < Ephp +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 91
    +    def init_converter(properties={})
    +      @pi = 'php'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Eruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Eruby.html new file mode 100644 index 0000000..8ee1195 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Eruby.html @@ -0,0 +1,155 @@ + + + + + + Class: Erubis::PI::Eruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Eruby
    In: + + erubis/engine/eruby.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 117
    +    def init_converter(properties={})
    +      @pi = 'rb'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Escheme.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Escheme.html new file mode 100644 index 0000000..8304f1c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/Escheme.html @@ -0,0 +1,166 @@ + + + + + + Class: Erubis::PI::Escheme + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::Escheme
    In: + + erubis/engine/escheme.rb + +
    +
    Parent: + PI::Engine +
    +
    + + +
    + + + +
    + +
    +

    +class XmlEscheme < Escheme +

    +
    +  include EscapeEnhancer
    +
    +

    +end +

    + +
    + + +
    + +
    +

    Methods

    + +
    + init_converter   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 106
    +    def init_converter(properties={})
    +      @pi = 'scheme'
    +      super(properties)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/TinyEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/TinyEruby.html new file mode 100644 index 0000000..5ade026 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PI/TinyEruby.html @@ -0,0 +1,293 @@ + + + + + + Class: Erubis::PI::TinyEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PI::TinyEruby
    In: + + erubis/tiny.rb + +
    +
    Parent: + Object +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + +
    + convert   + evaluate   + new   + result   +
    +
    + +
    + + + + +
    + + +
    +

    Constants

    + +
    + + + + + + +
    EMBEDDED_PATTERN=/(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m
    +
    +
    + + + +
    +

    Attributes

    + +
    + + + + + + +
    src [R] 
    +
    +
    + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 79
    +    def initialize(input=nil, options={})
    +      @escape  = options[:escape] || 'Erubis::XmlHelper.escape_xml'
    +      @src = convert(input) if input
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 88
    +    def convert(input)
    +      src = "_buf = '';"           # preamble
    +      pos = 0
    +      input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr|
    +        match = Regexp.last_match
    +        len   = match.begin(0) - pos
    +        text  = input[pos, len]
    +        pos   = match.end(0)
    +        #src << " _buf << '" << escape_text(text) << "';"
    +        text.gsub!(/['\\]/, '\\\\\&')
    +        src << " _buf << '" << text << "';" unless text.empty?
    +        if stmt                # <?rb ... ?>
    +          if lspace && rspace
    +            src << "#{lspace}#{stmt}#{rspace}"
    +          else
    +            src << " _buf << '" << lspace << "';" if lspace
    +            src << stmt << ";"
    +            src << " _buf << '" << rspace << "';" if rspace
    +          end
    +        else                       # ${...}, $!{...}
    +          if !indicator
    +            src << " _buf << " << @escape << "(" << expr << ");"
    +          elsif indicator == '!'
    +            src << " _buf << (" << expr << ").to_s;"
    +          end
    +        end
    +      end
    +      #rest = $' || input                        # ruby1.8
    +      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
    +      #src << " _buf << '" << escape_text(rest) << "';"
    +      rest.gsub!(/['\\]/, '\\\\\&')
    +      src << " _buf << '" << rest << "';" unless rest.empty?
    +      src << "\n_buf.to_s\n"       # postamble
    +      return src
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 132
    +    def evaluate(_context=Object.new)
    +      if _context.is_a?(Hash)
    +        _obj = Object.new
    +        _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
    +        _context = _obj
    +      end
    +      _context.instance_eval @src
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +def escape_text(text) +

    +
    +  return text.gsub!(/['\\]/, '\\\\\&') || text
    +
    +

    +end +

    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 128
    +    def result(_binding=TOPLEVEL_BINDING)
    +      eval @src, _binding
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PercentLineEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PercentLineEnhancer.html new file mode 100644 index 0000000..a7ed784 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PercentLineEnhancer.html @@ -0,0 +1,163 @@ + + + + + + Module: Erubis::PercentLineEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PercentLineEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +regards lines starting with ’%’ as program code +

    +

    +this is for compatibility to eruby and ERB. +

    +

    +this is language-independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_text   +
    +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 516
    +    def add_text(src, text)
    +      unless @prefixrexp
    +        @prefixchar = '%'
    +        @prefixrexp = /^\%(.*?\r?\n)/
    +      end
    +      super(src, text)
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PercentLineEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PercentLineEruby.html new file mode 100644 index 0000000..8621292 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PercentLineEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::PercentLineEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PercentLineEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PerlGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PerlGenerator.html new file mode 100644 index 0000000..f136c7a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PerlGenerator.html @@ -0,0 +1,344 @@ + + + + + + Module: Erubis::PerlGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PerlGenerator
    In: + + erubis/engine/eperl.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 49
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      s = code.gsub(/\'/, "\\'")
    +      src << @func << "('*** debug: #{code}=', #{code}, \"\\n\");"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 45
    +    def add_expr_escaped(src, code)
    +      add_expr_literal(src, escaped_expr(code))
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 40
    +    def add_expr_literal(src, code)
    +      code.strip!
    +      src << @func << "(" << code << "); "
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 59
    +    def add_postamble(src)
    +      src << "\n" unless src[-1] == ?\n
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 28
    +    def add_preamble(src)
    +      src << "use HTML::Entities; ";
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 55
    +    def add_stmt(src, code)
    +      src << code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 36
    +    def add_text(src, text)
    +      src << @func << "('" << escape_text(text) << "'); " unless text.empty?
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 32
    +    def escape_text(text)
    +      return text.gsub!(/['\\]/, '\\\\\&') || text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eperl.rb, line 22
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= 'encode_entities'
    +      @func = properties[:func] || 'print'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PhpGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PhpGenerator.html new file mode 100644 index 0000000..8b689a2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PhpGenerator.html @@ -0,0 +1,350 @@ + + + + + + Module: Erubis::PhpGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PhpGenerator
    In: + + erubis/engine/ephp.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 46
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      s = code.gsub(/\'/, "\\'")
    +      src << "<?php error_log('*** debug: #{s}='.(#{code}), 0); ?>"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 42
    +    def add_expr_escaped(src, code)
    +      add_expr_literal(src, escaped_expr(code))
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 37
    +    def add_expr_literal(src, code)
    +      code.strip!
    +      src << "<?php echo #{code}; ?>"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 63
    +    def add_postamble(src)
    +      # empty
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 25
    +    def add_preamble(src)
    +      # empty
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 52
    +    def add_stmt(src, code)
    +      src << "<?php"
    +      src << " " if code[0] != ?\ #
    +      if code[-1] == ?\n
    +        code.chomp!
    +        src << code << "?>\n"
    +      else
    +        src << code << "?>"
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 33
    +    def add_text(src, text)
    +      src << escape_text(text)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 29
    +    def escape_text(text)
    +      return text.gsub!(/<\?xml\b/, '<<?php ?>?xml') || text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/ephp.rb, line 20
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= 'htmlspecialchars'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrefixedLineEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrefixedLineEnhancer.html new file mode 100644 index 0000000..0069cdf --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrefixedLineEnhancer.html @@ -0,0 +1,210 @@ + + + + + + Module: Erubis::PrefixedLineEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PrefixedLineEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +regards lines starting with ’^[ \t]*%’ as program code +

    +

    +in addition you can specify prefix character (default ’%’) +

    +

    +this is language-independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_text   + init_generator   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 454
    +    def add_text(src, text)
    +      unless @prefixrexp
    +        @prefixchar ||= '%'
    +        @prefixrexp = Regexp.compile("^([ \\t]*)\\#{@prefixchar}(.*?\\r?\\n)")
    +      end
    +      pos = 0
    +      text2 = ''
    +      text.scan(@prefixrexp) do
    +        space = $1
    +        line  = $2
    +        space, line = '', $1 unless $2
    +        match = Regexp.last_match
    +        len   = match.begin(0) - pos
    +        str   = text[pos, len]
    +        pos   = match.end(0)
    +        if text2.empty?
    +          text2 = str
    +        else
    +          text2 << str
    +        end
    +        if line[0, 1] == @prefixchar
    +          text2 << space << line
    +        else
    +          super(src, text2)
    +          text2 = ''
    +          add_stmt(src, space + line)
    +        end
    +      end
    +      #rest = pos == 0 ? text : $'             # ruby1.8
    +      rest = pos == 0 ? text : text[pos..-1]   # ruby1.9
    +      unless text2.empty?
    +        text2 << rest if rest
    +        rest = text2
    +      end
    +      super(src, rest)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 449
    +    def init_generator(properties={})
    +      super
    +      @prefixchar = properties[:prefixchar]
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrefixedLineEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrefixedLineEruby.html new file mode 100644 index 0000000..93d8f2b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrefixedLineEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::PrefixedLineEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PrefixedLineEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PreprocessingEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PreprocessingEruby.html new file mode 100644 index 0000000..4f4c8da --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PreprocessingEruby.html @@ -0,0 +1,183 @@ + + + + + + Class: Erubis::PreprocessingEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PreprocessingEruby
    In: + + erubis/preprocessing.rb + +
    +
    Parent: + + Erubis::Eruby + +
    +
    + + +
    + + + +
    + +
    +

    +for preprocessing +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_expr_escaped   + new   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/preprocessing.rb, line 17
    +    def initialize(input, params={})
    +      params = params.dup
    +      params[:pattern] ||= '\[% %\]'    # use '[%= %]' instead of '<%= %>'
    +      #params[:escape] = true            # transport '[%= %]' and '[%== %]'
    +      super
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/preprocessing.rb, line 24
    +    def add_expr_escaped(src, code)
    +      add_expr_literal(src, "_decode((#{code}))")
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PreprocessingHelper.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PreprocessingHelper.html new file mode 100644 index 0000000..4f1e235 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PreprocessingHelper.html @@ -0,0 +1,212 @@ + + + + + + Module: Erubis::PreprocessingHelper + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PreprocessingHelper
    In: + + erubis/preprocessing.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +helper methods for preprocessing +

    + +
    + + +
    + +
    +

    Methods

    + +
    + _?   + _P   + _decode   + _p   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + +
    + _?(arg) +
    + +
    +

    +Alias for _p +

    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/preprocessing.rb, line 42
    +    def _P(arg)
    +      return "<%=h(#{arg})%>"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/preprocessing.rb, line 48
    +    def _decode(arg)
    +      arg = arg.to_s
    +      arg.gsub!(/%3C%25(?:=|%3D)(.*?)%25%3E/) { "<%=#{CGI.unescape($1)}%>" }
    +      arg.gsub!(/&lt;%=(.*?)%&gt;/) { "<%=#{CGI.unescapeHTML($1)}%>" }
    +      return arg
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/preprocessing.rb, line 38
    +    def _p(arg)
    +      return "<%=#{arg}%>"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintEnabledEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintEnabledEnhancer.html new file mode 100644 index 0000000..ff8022e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintEnabledEnhancer.html @@ -0,0 +1,212 @@ + + + + + + Module: Erubis::PrintEnabledEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PrintEnabledEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +enable print function +

    +

    +Notice: use Eruby#evaluate() and don‘t use Eruby#result() to be +enable print function. +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_preamble   + evaluate   + print   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 127
    +    def add_preamble(src)
    +      src << "@_buf = "
    +      super
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 138
    +    def evaluate(context=nil)
    +      _src = @src
    +      if context.is_a?(Hash)
    +        context.each do |key, val| instance_variable_set("@#{key}", val) end
    +      elsif context
    +        context.instance_variables.each do |name|
    +          instance_variable_set(name, context.instance_variable_get(name))
    +        end
    +      end
    +      return instance_eval(_src, (@filename || '(erubis)'))
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 132
    +    def print(*args)
    +      args.each do |arg|
    +        @_buf << arg.to_s
    +      end
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintEnabledEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintEnabledEruby.html new file mode 100644 index 0000000..c4efc94 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintEnabledEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::PrintEnabledEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PrintEnabledEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutEnhancer.html new file mode 100644 index 0000000..e1b1417 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutEnhancer.html @@ -0,0 +1,244 @@ + + + + + + Module: Erubis::PrintOutEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::PrintOutEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +use print statement instead of ‘_buf << …’ +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 102
    +    def add_expr_escaped(src, code)
    +      src << " print #{escaped_expr(code)};"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 98
    +    def add_expr_literal(src, code)
    +      src << " print((#{code}).to_s);"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 106
    +    def add_postamble(src)
    +      src << "\n" unless src[-1] == ?\n
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 91
    +    def add_preamble(src)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 94
    +    def add_text(src, text)
    +      src << " print '#{escape_text(text)}';" unless text.empty?
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutEruby.html new file mode 100644 index 0000000..b3a9b22 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::PrintOutEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PrintOutEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutSimplifiedEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutSimplifiedEruby.html new file mode 100644 index 0000000..8800630 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/PrintOutSimplifiedEruby.html @@ -0,0 +1,121 @@ + + + + + + Class: Erubis::PrintOutSimplifiedEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::PrintOutSimplifiedEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/RubyEvaluator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/RubyEvaluator.html new file mode 100644 index 0000000..c2e4066 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/RubyEvaluator.html @@ -0,0 +1,227 @@ + + + + + + Module: Erubis::RubyEvaluator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::RubyEvaluator
    In: + + erubis/evaluator.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +evaluator for Ruby +

    + +
    + + +
    + +
    +

    Methods

    + +
    + def_method   + evaluate   + result   +
    +
    + +
    + + + +
    +

    Included Modules

    + +
    + Evaluator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    +if object is an Class or Module then define instance method to it, else +define singleton method to it. +

    +

    [Source]

    +
    +
    +# File erubis/evaluator.rb, line 79
    +    def def_method(object, method_name, filename=nil)
    +      m = object.is_a?(Module) ? :module_eval : :instance_eval
    +      object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(erubis)')
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +invoke context.instance_eval(@src) +

    +

    [Source]

    +
    +
    +# File erubis/evaluator.rb, line 69
    +    def evaluate(_context=Context.new)
    +      _context = Context.new(_context) if _context.is_a?(Hash)
    +      #return _context.instance_eval(@src, @filename || '(erubis)')
    +      #@_proc ||= eval("proc { #{@src} }", Erubis::EMPTY_BINDING, @filename || '(erubis)')
    +      @_proc ||= eval("proc { #{@src} }", binding(), @filename || '(erubis)')
    +      return _context.instance_eval(&@_proc)
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +eval(@src) with binding object +

    +

    [Source]

    +
    +
    +# File erubis/evaluator.rb, line 53
    +    def result(_binding_or_hash=TOPLEVEL_BINDING)
    +      _arg = _binding_or_hash
    +      if _arg.is_a?(Hash)
    +        _b = binding()
    +        eval _arg.collect{|k,v| "#{k} = _arg[#{k.inspect}]; "}.join, _b
    +      elsif _arg.is_a?(Binding)
    +        _b = _arg
    +      elsif _arg.nil?
    +        _b = binding()
    +      else
    +        raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.")
    +      end
    +      return eval(@src, _b, (@filename || '(erubis'))
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/RubyGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/RubyGenerator.html new file mode 100644 index 0000000..436c1f4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/RubyGenerator.html @@ -0,0 +1,328 @@ + + + + + + Module: Erubis::RubyGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::RubyGenerator
    In: + + erubis/engine/eruby.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +code generator for Ruby +

    + +
    + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 63
    +    def add_expr_debug(src, code)
    +      code.strip!
    +      s = (code.dump =~ /\A"(.*)"\z/) && $1
    +      src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 59
    +    def add_expr_escaped(src, code)
    +      src << " #{@bufvar} << " << escaped_expr(code) << ';'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 55
    +    def add_expr_literal(src, code)
    +      src << " #{@bufvar} << (" << code << ').to_s;'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 49
    +    def add_stmt(src, code)
    +      #src << code << ';'
    +      src << code
    +      src << ';' unless code[-1] == ?\n
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 45
    +    def add_text(src, text)
    +      src << " #{@bufvar} << '" << escape_text(text) << "';" unless text.empty?
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 31
    +    def escape_text(text)
    +      text.gsub(/['\\]/, '\\\\\&')   # "'" => "\\'",  '\\' => '\\\\'
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 35
    +    def escaped_expr(code)
    +      return "#{@escapefunc}(#{code})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/eruby.rb, line 21
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= "Erubis::XmlHelper.escape_xml"
    +      @bufvar     = properties[:bufvar] || "_buf"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SchemeGenerator.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SchemeGenerator.html new file mode 100644 index 0000000..dce177a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SchemeGenerator.html @@ -0,0 +1,382 @@ + + + + + + Module: Erubis::SchemeGenerator + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::SchemeGenerator
    In: + + erubis/engine/escheme.rb + +
    +
    +
    + + +
    + + + +
    + + + +
    + +
    +

    Methods

    + + +
    + +
    + + + +
    +

    Included Modules

    + +
    + Generator +
    +
    + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 71
    +    def add_expr_debug(src, code)
    +      s = (code.strip! || code).gsub(/\"/, '\\"')
    +      src << "(display \"*** debug: #{s}=\")(display #{code.strip})(display \"\\n\")"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 67
    +    def add_expr_escaped(src, code)
    +      add_expr_literal(src, escaped_expr(code))
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 62
    +    def add_expr_literal(src, code)
    +      code.strip!
    +      src << "(#{@func} #{code})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 76
    +    def add_postamble(src)
    +      return unless @func == '_add'
    +      src << "\n" unless src[-1] == ?\n
    +      src << "  (reverse _buf))\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 28
    +    def add_preamble(src)
    +      return unless @func == '_add'
    +      src << "(let ((_buf '())) " + \
    +               "(define (_add x) (set! _buf (cons x _buf))) "
    +      #src << "(let* ((_buf '())" +        #             " (_add (lambda (x) (set! _buf (cons x _buf))))) "
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 58
    +    def add_stmt(src, code)
    +      src << code
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 47
    +    def add_text(src, text)
    +      return if text.empty?
    +      t = escape_text(text)
    +      if t[-1] == ?\n
    +        t[-1, 1] = ''
    +        src << "(#{@func} \"" << t << "\\n\")\n"
    +      else
    +        src << "(#{@func} \"" << t << '")'
    +      end
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 36
    +    def escape_text(text)
    +      @table_ ||= { '"'=>'\\"', '\\'=>'\\\\' }
    +      text.gsub!(/["\\]/) { |m| @table_[m] }
    +      return text
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 42
    +    def escaped_expr(code)
    +      code.strip!
    +      return "(#{@escapefunc} #{code})"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/engine/escheme.rb, line 22
    +    def init_generator(properties={})
    +      super
    +      @escapefunc ||= 'escape'
    +      @func = properties[:func] || '_add'   # or 'display'
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SimplifiedEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SimplifiedEruby.html new file mode 100644 index 0000000..01adfea --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SimplifiedEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::SimplifiedEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::SimplifiedEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SimplifyEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SimplifyEnhancer.html new file mode 100644 index 0000000..1e033d8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/SimplifyEnhancer.html @@ -0,0 +1,191 @@ + + + + + + Module: Erubis::SimplifyEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::SimplifyEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +get convert faster, but spaces +around ’<%…%>’ are not trimmed. +

    +

    +this is language-independent. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + convert   +
    +
    + +
    + + + + +
    + + +
    +

    Constants

    + +
    + + + + + + + + +
    SIMPLE_REGEXP=/<%(=+|\#)?(.*?)-?%>/m  +DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + +
    +
    +
    + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 342
    +    def convert(input)
    +      src = ""
    +      add_preamble(src)
    +      #regexp = pattern_regexp(@pattern)
    +      pos = 0
    +      input.scan(SIMPLE_REGEXP) do |indicator, code|
    +        match = Regexp.last_match
    +        index = match.begin(0)
    +        text  = input[pos, index - pos]
    +        pos   = match.end(0)
    +        add_text(src, text)
    +        if !indicator              # <% %>
    +          add_stmt(src, code)
    +        elsif indicator[0] == ?\#  # <%# %>
    +          n = code.count("\n")
    +          add_stmt(src, "\n" * n)
    +        else                       # <%= %>
    +          add_expr(src, code, indicator)
    +        end
    +      end
    +      #rest = $' || input                      # ruby1.8
    +      rest = pos == 0 ? input : input[pos..-1]  # ruby1.9
    +      add_text(src, rest)
    +      add_postamble(src)
    +      return src
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutEnhancer.html new file mode 100644 index 0000000..05e37ba --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutEnhancer.html @@ -0,0 +1,173 @@ + + + + + + Module: Erubis::StdoutEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::StdoutEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +use $stdout instead of string +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_postamble   + add_preamble   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 73
    +    def add_postamble(src)
    +      src << "\n''\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 69
    +    def add_preamble(src)
    +      src << "#{@bufvar} = $stdout;"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutEruby.html new file mode 100644 index 0000000..bd6eadb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::StdoutEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::StdoutEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutSimplifiedEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutSimplifiedEruby.html new file mode 100644 index 0000000..e6ec46d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StdoutSimplifiedEruby.html @@ -0,0 +1,121 @@ + + + + + + Class: Erubis::StdoutSimplifiedEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::StdoutSimplifiedEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringBufferEnhancer.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringBufferEnhancer.html new file mode 100644 index 0000000..8b14c93 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringBufferEnhancer.html @@ -0,0 +1,174 @@ + + + + + + Module: Erubis::StringBufferEnhancer + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::StringBufferEnhancer
    In: + + erubis/enhancer.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +use String class for buffering +

    +

    +this is only for Eruby. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + add_postamble   + add_preamble   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 214
    +    def add_postamble(src)
    +      src << "\n" unless src[-1] == ?\n
    +      src << "#{@bufvar}.to_s\n"
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/enhancer.rb, line 210
    +    def add_preamble(src)
    +      src << "#{@bufvar} = '';"
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringBufferEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringBufferEruby.html new file mode 100644 index 0000000..1e39331 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringBufferEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::StringBufferEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::StringBufferEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringIOEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringIOEruby.html new file mode 100644 index 0000000..c1bcb98 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/StringIOEruby.html @@ -0,0 +1,120 @@ + + + + + + Class: Erubis::StringIOEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::StringIOEruby
    In: + + erubis/engine/enhanced.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + + + +
    + + +
    + + + +
    +

    Included Modules

    + +
    + StringIOEnhancer +
    +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/TinyEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/TinyEruby.html new file mode 100644 index 0000000..6c9abc2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/TinyEruby.html @@ -0,0 +1,298 @@ + + + + + + Class: Erubis::TinyEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::TinyEruby
    In: + + erubis/tiny.rb + +
    +
    Parent: + Object +
    +
    + + +
    + + + +
    + +
    +

    +tiny and the simplest implementation of eRuby +

    +

    +ex. +

    +
    +  eruby = TinyEruby.new(File.read('example.rhtml'))
    +  print eruby.src                 # print ruby code
    +  print eruby.result(binding())   # eval ruby code with Binding object
    +  print eruby.evalute(context)    # eval ruby code with context object
    +
    + +
    + + +
    + +
    +

    Methods

    + +
    + convert   + evaluate   + new   + result   +
    +
    + +
    + + + + +
    + + +
    +

    Constants

    + +
    + + + + + + +
    EMBEDDED_PATTERN=/<%(=+|\#)?(.*?)-?%>/m
    +
    +
    + + + +
    +

    Attributes

    + +
    + + + + + + +
    src [R] 
    +
    +
    + + + + +
    +

    Public Class methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 19
    +    def initialize(input=nil)
    +      @src = convert(input) if input
    +    end
    +
    +
    +
    +
    + +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 26
    +    def convert(input)
    +      src = "_buf = '';"           # preamble
    +      pos = 0
    +      input.scan(EMBEDDED_PATTERN) do |indicator, code|
    +        m = Regexp.last_match
    +        text = input[pos...m.begin(0)]
    +        pos  = m.end(0)
    +        #src << " _buf << '" << escape_text(text) << "';"
    +        text.gsub!(/['\\]/, '\\\\\&')
    +        src << " _buf << '" << text << "';" unless text.empty?
    +        if !indicator              # <% %>
    +          src << code << ";"
    +        elsif indicator == '#'     # <%# %>
    +          src << ("\n" * code.count("\n"))
    +        else                       # <%= %>
    +          src << " _buf << (" << code << ").to_s;"
    +        end
    +      end
    +      #rest = $' || input                        # ruby1.8
    +      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
    +      #src << " _buf << '" << escape_text(rest) << "';"
    +      rest.gsub!(/['\\]/, '\\\\\&')
    +      src << " _buf << '" << rest << "';" unless rest.empty?
    +      src << "\n_buf.to_s\n"       # postamble
    +      return src
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 61
    +    def evaluate(_context=Object.new)
    +      if _context.is_a?(Hash)
    +        _obj = Object.new
    +        _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
    +        _context = _obj
    +      end
    +      _context.instance_eval @src
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    +def escape_text(text) +

    +
    +  return text.gsub!(/['\\]/, '\\\\\&') || text
    +
    +

    +end +

    +

    [Source]

    +
    +
    +# File erubis/tiny.rb, line 57
    +    def result(_binding=TOPLEVEL_BINDING)
    +      eval @src, _binding
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/XmlEruby.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/XmlEruby.html new file mode 100644 index 0000000..45a769a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/XmlEruby.html @@ -0,0 +1,130 @@ + + + + + + Class: Erubis::XmlEruby + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    ClassErubis::XmlEruby
    In: + + erubis/engine/eruby.rb + +
    +
    Parent: + + Eruby + +
    +
    + + +
    + + + +
    + +
    +

    +sanitize expression (<%= … %>) by default +

    +

    +this is equivalent to EscapedEruby and is +prepared only for compatibility. +

    + +
    + + +
    + + +
    + + + +
    +

    Included Modules

    + + +
    + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/XmlHelper.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/XmlHelper.html new file mode 100644 index 0000000..9718750 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Erubis/XmlHelper.html @@ -0,0 +1,255 @@ + + + + + + Module: Erubis::XmlHelper + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleErubis::XmlHelper
    In: + + erubis/helper.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +helper for xml +

    + +
    + + +
    + +
    +

    Methods

    + +
    + escape_xml   + escape_xml2   + h   + html_escape   + u   + url_encode   +
    +
    + +
    + + + + +
    + + +
    +

    Constants

    + +
    + + + + + + +
    ESCAPE_TABLE={ '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', '"' => '&quot;', "'" => '&#039;', }
    +
    +
    + + + + + + + +
    +

    Public Instance methods

    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helper.rb, line 24
    +    def escape_xml(value)
    +      value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] }   # or /[&<>"']/
    +      #value.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
    +    end
    +
    +
    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helper.rb, line 29
    +    def escape_xml2(value)
    +      return value.to_s.gsub(/\&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;').gsub(/"/,'&quot;')
    +    end
    +
    +
    +
    +
    + +
    + + +
    + h(value) +
    + +
    +

    +Alias for escape_xml +

    +
    +
    + +
    + + +
    + html_escape(value) +
    + +
    +

    +Alias for escape_xml +

    +
    +
    + +
    + + +
    + u(str) +
    + +
    +

    +Alias for url_encode +

    +
    +
    + +
    + + + + +
    +

    [Source]

    +
    +
    +# File erubis/helper.rb, line 36
    +    def url_encode(str)
    +      return str.gsub(/[^-_.a-zA-Z0-9]+/) { |s|
    +        s.unpack('C*').collect { |i| "%%%02X" % i }.join
    +      }
    +    end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Kernel.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Kernel.html new file mode 100644 index 0000000..237d745 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/classes/Kernel.html @@ -0,0 +1,155 @@ + + + + + + Module: Kernel + + + + + + + + + + +
    + + + + + + + + + + +
    ModuleKernel
    In: + + erubis/util.rb + +
    +
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + +
    +

    Methods

    + +
    + not_implemented   +
    +
    + +
    + + + + +
    + + + + + + + + + +
    +

    Private Instance methods

    + +
    + + + + +
    +

    +raise NotImplementedError +

    +

    [Source]

    +
    +
    +# File erubis/util.rb, line 11
    +  def not_implemented     #:doc:
    +    backtrace = caller()
    +    method_name = (backtrace.shift =~ /`(\w+)'$/) && $1
    +    mesg = "class #{self.class.name} must implement abstract method '#{method_name}()'."
    +    #mesg = "#{self.class.name}##{method_name}() is not implemented."
    +    err = NotImplementedError.new mesg
    +    err.set_backtrace backtrace
    +    raise err
    +  end
    +
    +
    +
    +
    + + +
    + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/created.rid b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/created.rid new file mode 100644 index 0000000..b2c7859 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/created.rid @@ -0,0 +1 @@ +Sat, 02 Apr 2011 07:53:01 +0900 diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/README_txt.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/README_txt.html new file mode 100644 index 0000000..4a91039 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/README_txt.html @@ -0,0 +1,247 @@ + + + + + + File: README.txt + + + + + + + + + + +
    +

    README.txt

    + + + + + + + + + +
    Path:README.txt +
    Last Update:Sat Apr 02 07:53:01 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    README

    + + + +
    release:2.7.0 + +
    copyright:copyright(c) 2006-2011 kuwata-lab.com all rights reserved. + +
    +

    About Erubis

    +

    +Erubis is an implementation of eRuby. +It has the following features. +

    +
      +
    • Very fast, almost three times faster than ERB and even 10% faster than eruby + +
    • +
    • Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) + +
    • +
    • Auto escaping support + +
    • +
    • Auto trimming spaces around ’<% %>’ + +
    • +
    • Embedded pattern changeable (default ’<% %>’) + +
    • +
    • Enable to handle Processing Instructions (PI) as embedded pattern (ex. +’<?rb … ?>’) + +
    • +
    • Context object available and easy to combine eRuby template with YAML +datafile + +
    • +
    • Print statement available + +
    • +
    • Easy to extend and customize in subclass + +
    • +
    • Ruby on Rails support + +
    • +
    +

    +Erubis is implemented in pure Ruby. It +requires Ruby 1.8 or higher. Erubis +now supports Ruby 1.9. +

    +

    +See doc/users-guide.html for details. +

    +

    Installation

    +
      +
    • If you have installed RubyGems, just type gem install erubis. + +
      +  $ sudo gem install erubis
      +
      +
    • +
    • Else install abstract +at first, and download erubis_X.X.X.tar.bz2 and install it by setup.rb. + +
      +  $ tar xjf abstract_X.X.X.tar.bz2
      +  $ cd abstract_X.X.X/
      +  $ sudo ruby setup.rb
      +  $ cd ..
      +  $ tar xjf erubis_X.X.X.tar.bz2
      +  $ cd erubis_X.X.X/
      +  $ sudo ruby setup.rb
      +
      +
    • +
    • (Optional) It is able to merge ‘lib/**/*.rb’ into +‘bin/erubis’ by ‘contrib/inline-require’ script. + +
      +  $ tar xjf erubis_X.X.X.tar.bz2
      +  $ cd erubis_X.X.X/
      +  $ cp /tmp/abstract_X.X.X/lib/abstract.rb lib
      +  $ unset RUBYLIB
      +  $ contrib/inline-require -I lib bin/erubis > contrib/erubis
      +
      +
    • +
    +

    Ruby on Rails Support

    +

    +Erubis supports Ruby on Rails. All you +have to do is to add the following code into your +‘config/environment.rb’ and restart web server. +

    +
    +     require 'erubis/helpers/rails_helper'
    +     #Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby
    +     #Erubis::Helpers::RailsHelper.init_properties = {}
    +     #Erubis::Helpers::RailsHelper.show_src = nil
    +
    +

    +If Erubis::Helpers::RailsHelper.show_src is ture, Erubis prints converted Ruby code into +log file (‘log/development.log’ or so). It is useful for debug. +

    +

    Exploring Guide

    +

    +If you are exploring Eruby, see the following class at first. +

    +
      +
    • Erubis::TinyEruby +(erubis/tiny.rb) — the most simple eRuby implementation. + +
    • +
    • Erubis::Engine +(erubis/engine.rb) — base class of Eruby, Ephp, Ejava, and so on. + +
    • +
    • Erubis::Eruby +(erubis/engine/eruby.rb) — engine class for eRuby. + +
    • +
    • Erubis::Converter +(erubis/converter.rb) — convert eRuby script into Ruby code. + +
    • +
    +

    Benchmark

    +

    +‘benchmark/erubybenchmark.rb’ is a benchmark script of Erubis. Try ‘ruby +erubybenchmark.rb’ in benchmark directory. +

    +

    License

    +

    +MIT License +

    +

    Author

    +

    +makoto kuwata <kwa(at)kuwata-lab.com> +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/context_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/context_rb.html new file mode 100644 index 0000000..e535372 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/context_rb.html @@ -0,0 +1,107 @@ + + + + + + File: context.rb + + + + + + + + + + +
    +

    context.rb

    + + + + + + + + + +
    Path:erubis/context.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/converter_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/converter_rb.html new file mode 100644 index 0000000..9256edc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/converter_rb.html @@ -0,0 +1,114 @@ + + + + + + File: converter.rb + + + + + + + + + + +
    +

    converter.rb

    + + + + + + + + + +
    Path:erubis/converter.rb +
    Last Update:Tue Mar 22 15:43:22 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + +
    + erubis/util   +
    +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ec_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ec_rb.html new file mode 100644 index 0000000..52b1b89 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ec_rb.html @@ -0,0 +1,115 @@ + + + + + + File: ec.rb + + + + + + + + + + +
    +

    ec.rb

    + + + + + + + + + +
    Path:erubis/engine/ec.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ecpp_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ecpp_rb.html new file mode 100644 index 0000000..a6ed996 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ecpp_rb.html @@ -0,0 +1,115 @@ + + + + + + File: ecpp.rb + + + + + + + + + + +
    +

    ecpp.rb

    + + + + + + + + + +
    Path:erubis/engine/ecpp.rb +
    Last Update:Tue Mar 22 16:31:59 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ejava_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ejava_rb.html new file mode 100644 index 0000000..ef661be --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ejava_rb.html @@ -0,0 +1,115 @@ + + + + + + File: ejava.rb + + + + + + + + + + +
    +

    ejava.rb

    + + + + + + + + + +
    Path:erubis/engine/ejava.rb +
    Last Update:Mon Mar 21 20:51:19 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ejavascript_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ejavascript_rb.html new file mode 100644 index 0000000..50982c6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ejavascript_rb.html @@ -0,0 +1,115 @@ + + + + + + File: ejavascript.rb + + + + + + + + + + +
    +

    ejavascript.rb

    + + + + + + + + + +
    Path:erubis/engine/ejavascript.rb +
    Last Update:Mon Mar 21 20:50:10 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/enhanced_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/enhanced_rb.html new file mode 100644 index 0000000..7dcb5e5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/enhanced_rb.html @@ -0,0 +1,115 @@ + + + + + + File: enhanced.rb + + + + + + + + + + +
    +

    enhanced.rb

    + + + + + + + + + +
    Path:erubis/engine/enhanced.rb +
    Last Update:Tue Feb 22 21:00:22 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/eperl_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/eperl_rb.html new file mode 100644 index 0000000..f69476b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/eperl_rb.html @@ -0,0 +1,115 @@ + + + + + + File: eperl.rb + + + + + + + + + + +
    +

    eperl.rb

    + + + + + + + + + +
    Path:erubis/engine/eperl.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ephp_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ephp_rb.html new file mode 100644 index 0000000..98e9cb8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/ephp_rb.html @@ -0,0 +1,115 @@ + + + + + + File: ephp.rb + + + + + + + + + + +
    +

    ephp.rb

    + + + + + + + + + +
    Path:erubis/engine/ephp.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/eruby_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/eruby_rb.html new file mode 100644 index 0000000..ccb4c95 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/eruby_rb.html @@ -0,0 +1,115 @@ + + + + + + File: eruby.rb + + + + + + + + + + +
    +

    eruby.rb

    + + + + + + + + + +
    Path:erubis/engine/eruby.rb +
    Last Update:Mon Mar 21 20:46:28 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/escheme_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/escheme_rb.html new file mode 100644 index 0000000..440cc72 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/escheme_rb.html @@ -0,0 +1,115 @@ + + + + + + File: escheme.rb + + + + + + + + + + +
    +

    escheme.rb

    + + + + + + + + + +
    Path:erubis/engine/escheme.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/optimized_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/optimized_rb.html new file mode 100644 index 0000000..44d0162 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine/optimized_rb.html @@ -0,0 +1,114 @@ + + + + + + File: optimized.rb + + + + + + + + + + +
    +

    optimized.rb

    + + + + + + + + + +
    Path:erubis/engine/optimized.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine_rb.html new file mode 100644 index 0000000..b3a9d5e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/engine_rb.html @@ -0,0 +1,117 @@ + + + + + + File: engine.rb + + + + + + + + + + +
    +

    engine.rb

    + + + + + + + + + +
    Path:erubis/engine.rb +
    Last Update:Mon Mar 21 08:26:29 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/enhancer_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/enhancer_rb.html new file mode 100644 index 0000000..50294a2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/enhancer_rb.html @@ -0,0 +1,107 @@ + + + + + + File: enhancer.rb + + + + + + + + + + +
    +

    enhancer.rb

    + + + + + + + + + +
    Path:erubis/enhancer.rb +
    Last Update:Mon Mar 21 20:39:56 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/error_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/error_rb.html new file mode 100644 index 0000000..2d81927 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/error_rb.html @@ -0,0 +1,107 @@ + + + + + + File: error.rb + + + + + + + + + + +
    +

    error.rb

    + + + + + + + + + +
    Path:erubis/error.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/evaluator_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/evaluator_rb.html new file mode 100644 index 0000000..791c3fb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/evaluator_rb.html @@ -0,0 +1,115 @@ + + + + + + File: evaluator.rb + + + + + + + + + + +
    +

    evaluator.rb

    + + + + + + + + + +
    Path:erubis/evaluator.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/generator_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/generator_rb.html new file mode 100644 index 0000000..0f11b07 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/generator_rb.html @@ -0,0 +1,114 @@ + + + + + + File: generator.rb + + + + + + + + + + +
    +

    generator.rb

    + + + + + + + + + +
    Path:erubis/generator.rb +
    Last Update:Mon Mar 21 09:35:40 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + +
    + erubis/util   +
    +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helper_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helper_rb.html new file mode 100644 index 0000000..bf001fc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helper_rb.html @@ -0,0 +1,107 @@ + + + + + + File: helper.rb + + + + + + + + + + +
    +

    helper.rb

    + + + + + + + + + +
    Path:erubis/helper.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helpers/rails_form_helper_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helpers/rails_form_helper_rb.html new file mode 100644 index 0000000..de19da5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helpers/rails_form_helper_rb.html @@ -0,0 +1,107 @@ + + + + + + File: rails_form_helper.rb + + + + + + + + + + +
    +

    rails_form_helper.rb

    + + + + + + + + + +
    Path:erubis/helpers/rails_form_helper.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helpers/rails_helper_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helpers/rails_helper_rb.html new file mode 100644 index 0000000..8ae3383 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/helpers/rails_helper_rb.html @@ -0,0 +1,116 @@ + + + + + + File: rails_helper.rb + + + + + + + + + + +
    +

    rails_helper.rb

    + + + + + + + + + +
    Path:erubis/helpers/rails_helper.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + +
    + erubis   + erubis/preprocessing   + action_pack/version   +
    +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/local-setting_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/local-setting_rb.html new file mode 100644 index 0000000..246a0d7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/local-setting_rb.html @@ -0,0 +1,107 @@ + + + + + + File: local-setting.rb + + + + + + + + + + +
    +

    local-setting.rb

    + + + + + + + + + +
    Path:erubis/local-setting.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/main_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/main_rb.html new file mode 100644 index 0000000..97f75f3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/main_rb.html @@ -0,0 +1,129 @@ + + + + + + File: main.rb + + + + + + + + + + +
    +

    main.rb

    + + + + + + + + + +
    Path:erubis/main.rb +
    Last Update:Tue Mar 22 16:31:59 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/preprocessing_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/preprocessing_rb.html new file mode 100644 index 0000000..10e6b33 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/preprocessing_rb.html @@ -0,0 +1,114 @@ + + + + + + File: preprocessing.rb + + + + + + + + + + +
    +

    preprocessing.rb

    + + + + + + + + + +
    Path:erubis/preprocessing.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + +
    + cgi   +
    +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/tiny_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/tiny_rb.html new file mode 100644 index 0000000..6c5feca --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/tiny_rb.html @@ -0,0 +1,107 @@ + + + + + + File: tiny.rb + + + + + + + + + + +
    +

    tiny.rb

    + + + + + + + + + +
    Path:erubis/tiny.rb +
    Last Update:Tue Jul 14 09:47:22 +0900 2009
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/util_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/util_rb.html new file mode 100644 index 0000000..b5a923d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis/util_rb.html @@ -0,0 +1,107 @@ + + + + + + File: util.rb + + + + + + + + + + +
    +

    util.rb

    + + + + + + + + + +
    Path:erubis/util.rb +
    Last Update:Mon Mar 21 09:32:48 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis_rb.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis_rb.html new file mode 100644 index 0000000..2d192e4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/files/erubis_rb.html @@ -0,0 +1,118 @@ + + + + + + File: erubis.rb + + + + + + + + + + +
    +

    erubis.rb

    + + + + + + + + + +
    Path:erubis.rb +
    Last Update:Mon Mar 21 09:44:53 +0900 2011
    +
    + + +
    + + + +
    + +
    +

    +$Release: 2.7.0 $ copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +

    + +
    + +
    +

    Required files

    + + +
    + +
    + + +
    + + + + +
    + + + + + + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_class_index.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_class_index.html new file mode 100644 index 0000000..79d9617 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_class_index.html @@ -0,0 +1,129 @@ + + + + + + + + Classes + + + + + +
    +

    Classes

    +
    + ActionView
    + ActionView::TemplateHandlers::ErubisHandler
    + ERB
    + Erubis
    + Erubis::ArrayBufferEnhancer
    + Erubis::ArrayBufferEruby
    + Erubis::ArrayEnhancer
    + Erubis::ArrayEruby
    + Erubis::Basic
    + Erubis::Basic::Converter
    + Erubis::Basic::Engine
    + Erubis::BiPatternEnhancer
    + Erubis::BiPatternEruby
    + Erubis::CGenerator
    + Erubis::CommandOptionError
    + Erubis::Context
    + Erubis::Converter
    + Erubis::CppGenerator
    + Erubis::DeleteIndentEnhancer
    + Erubis::DeleteIndentEruby
    + Erubis::Ec
    + Erubis::Ecpp
    + Erubis::Ejava
    + Erubis::Ejavascript
    + Erubis::Engine
    + Erubis::Eperl
    + Erubis::Ephp
    + Erubis::ErboutEnhancer
    + Erubis::ErboutEruby
    + Erubis::ErubisError
    + Erubis::Eruby
    + Erubis::EscapeEnhancer
    + Erubis::EscapedEc
    + Erubis::EscapedEcpp
    + Erubis::EscapedEjava
    + Erubis::EscapedEjavascript
    + Erubis::EscapedEperl
    + Erubis::EscapedEphp
    + Erubis::EscapedEruby
    + Erubis::EscapedEscheme
    + Erubis::Escheme
    + Erubis::Evaluator
    + Erubis::FastEruby
    + Erubis::Generator
    + Erubis::HeaderFooterEnhancer
    + Erubis::HeaderFooterEruby
    + Erubis::Helpers
    + Erubis::Helpers::RailsFormHelper
    + Erubis::Helpers::RailsHelper
    + Erubis::Helpers::RailsHelper::TemplateConverter
    + Erubis::InterpolationEnhancer
    + Erubis::InterpolationEruby
    + Erubis::JavaGenerator
    + Erubis::JavascriptGenerator
    + Erubis::Main
    + Erubis::NoCodeEnhancer
    + Erubis::NoCodeEruby
    + Erubis::NoTextEnhancer
    + Erubis::NoTextEruby
    + Erubis::NotSupportedError
    + Erubis::OptimizedEruby
    + Erubis::OptimizedGenerator
    + Erubis::OptimizedXmlEruby
    + Erubis::PI
    + Erubis::PI::Converter
    + Erubis::PI::Ec
    + Erubis::PI::Ecpp
    + Erubis::PI::Ejava
    + Erubis::PI::Ejavascript
    + Erubis::PI::Engine
    + Erubis::PI::Eperl
    + Erubis::PI::Ephp
    + Erubis::PI::Eruby
    + Erubis::PI::Escheme
    + Erubis::PI::TinyEruby
    + Erubis::PercentLineEnhancer
    + Erubis::PercentLineEruby
    + Erubis::PerlGenerator
    + Erubis::PhpGenerator
    + Erubis::PrefixedLineEnhancer
    + Erubis::PrefixedLineEruby
    + Erubis::PreprocessingEruby
    + Erubis::PreprocessingHelper
    + Erubis::PrintEnabledEnhancer
    + Erubis::PrintEnabledEruby
    + Erubis::PrintOutEnhancer
    + Erubis::PrintOutEruby
    + Erubis::PrintOutSimplifiedEruby
    + Erubis::RubyEvaluator
    + Erubis::RubyGenerator
    + Erubis::SchemeGenerator
    + Erubis::SimplifiedEruby
    + Erubis::SimplifyEnhancer
    + Erubis::StdoutEnhancer
    + Erubis::StdoutEruby
    + Erubis::StdoutSimplifiedEruby
    + Erubis::StringBufferEnhancer
    + Erubis::StringBufferEruby
    + Erubis::StringIOEruby
    + Erubis::TinyEruby
    + Erubis::XmlEruby
    + Erubis::XmlHelper
    + Kernel
    +
    +
    + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_file_index.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_file_index.html new file mode 100644 index 0000000..ef20605 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_file_index.html @@ -0,0 +1,53 @@ + + + + + + + + Files + + + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_method_index.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_method_index.html new file mode 100644 index 0000000..f39a25d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/fr_method_index.html @@ -0,0 +1,265 @@ + + + + + + + + Methods + + + + + +
    +

    Methods

    +
    + [] (Erubis::Context)
    + []= (Erubis::Context)
    + _? (Erubis::PreprocessingHelper)
    + _P (Erubis::PreprocessingHelper)
    + _add_text_to_str (Erubis::InterpolationEnhancer)
    + _create_preprocessor (Erubis::Helpers::RailsHelper::TemplateConverter)
    + _decode (Erubis::PreprocessingHelper)
    + _logger_info (Erubis::Helpers::RailsHelper::TemplateConverter)
    + _logger_info (Erubis::Helpers::RailsHelper::TemplateConverter)
    + _p (Erubis::PreprocessingHelper)
    + _pp_check_box_checked? (Erubis::Helpers::RailsFormHelper)
    + _pp_error_tags (Erubis::Helpers::RailsFormHelper)
    + _pp_radio_button_checked? (Erubis::Helpers::RailsFormHelper)
    + _pp_remove_error_div (Erubis::Helpers::RailsFormHelper)
    + _pp_select (Erubis::Helpers::RailsFormHelper)
    + _pp_select_options (Erubis::Helpers::RailsFormHelper)
    + _preprocessing_context_object (Erubis::Helpers::RailsHelper::TemplateConverter)
    + add_expr (Erubis::Basic::Converter)
    + add_expr (Erubis::NoCodeEnhancer)
    + add_expr (Erubis::EscapeEnhancer)
    + add_expr_debug (Erubis::PhpGenerator)
    + add_expr_debug (Erubis::JavascriptGenerator)
    + add_expr_debug (Erubis::CGenerator)
    + add_expr_debug (Erubis::OptimizedXmlEruby)
    + add_expr_debug (Erubis::CppGenerator)
    + add_expr_debug (Erubis::RubyGenerator)
    + add_expr_debug (Erubis::JavaGenerator)
    + add_expr_debug (Erubis::OptimizedGenerator)
    + add_expr_debug (Erubis::PerlGenerator)
    + add_expr_debug (Erubis::Generator)
    + add_expr_debug (Erubis::SchemeGenerator)
    + add_expr_escaped (Erubis::InterpolationEnhancer)
    + add_expr_escaped (Erubis::PhpGenerator)
    + add_expr_escaped (Erubis::OptimizedGenerator)
    + add_expr_escaped (Erubis::SchemeGenerator)
    + add_expr_escaped (Erubis::CppGenerator)
    + add_expr_escaped (Erubis::JavascriptGenerator)
    + add_expr_escaped (Erubis::PreprocessingEruby)
    + add_expr_escaped (Erubis::JavaGenerator)
    + add_expr_escaped (Erubis::PrintOutEnhancer)
    + add_expr_escaped (Erubis::RubyGenerator)
    + add_expr_escaped (Erubis::Generator)
    + add_expr_escaped (Erubis::CGenerator)
    + add_expr_escaped (Erubis::PerlGenerator)
    + add_expr_literal (Erubis::SchemeGenerator)
    + add_expr_literal (Erubis::JavaGenerator)
    + add_expr_literal (Erubis::PrintOutEnhancer)
    + add_expr_literal (Erubis::OptimizedGenerator)
    + add_expr_literal (Erubis::Generator)
    + add_expr_literal (Erubis::CGenerator)
    + add_expr_literal (Erubis::InterpolationEnhancer)
    + add_expr_literal (Erubis::PhpGenerator)
    + add_expr_literal (Erubis::CppGenerator)
    + add_expr_literal (Erubis::JavascriptGenerator)
    + add_expr_literal (Erubis::RubyGenerator)
    + add_expr_literal (Erubis::PerlGenerator)
    + add_indent (Erubis::JavascriptGenerator)
    + add_postamble (Erubis::ErboutEnhancer)
    + add_postamble (Erubis::SchemeGenerator)
    + add_postamble (Erubis::OptimizedGenerator)
    + add_postamble (Erubis::JavaGenerator)
    + add_postamble (Erubis::ArrayEnhancer)
    + add_postamble (Erubis::CGenerator)
    + add_postamble (Erubis::StdoutEnhancer)
    + add_postamble (Erubis::PrintOutEnhancer)
    + add_postamble (Erubis::StringBufferEnhancer)
    + add_postamble (Erubis::Generator)
    + add_postamble (Erubis::JavascriptGenerator)
    + add_postamble (Erubis::PhpGenerator)
    + add_postamble (Erubis::ArrayBufferEnhancer)
    + add_postamble (Erubis::NoCodeEnhancer)
    + add_postamble (Erubis::PerlGenerator)
    + add_postamble (Erubis::CppGenerator)
    + add_preamble (Erubis::PrintEnabledEnhancer)
    + add_preamble (Erubis::JavascriptGenerator)
    + add_preamble (Erubis::NoCodeEnhancer)
    + add_preamble (Erubis::PhpGenerator)
    + add_preamble (Erubis::ArrayBufferEnhancer)
    + add_preamble (Erubis::StdoutEnhancer)
    + add_preamble (Erubis::PrintOutEnhancer)
    + add_preamble (Erubis::Generator)
    + add_preamble (Erubis::CGenerator)
    + add_preamble (Erubis::CppGenerator)
    + add_preamble (Erubis::StringBufferEnhancer)
    + add_preamble (Erubis::ArrayEnhancer)
    + add_preamble (Erubis::JavaGenerator)
    + add_preamble (Erubis::OptimizedGenerator)
    + add_preamble (Erubis::PerlGenerator)
    + add_preamble (Erubis::SchemeGenerator)
    + add_preamble (Erubis::ErboutEnhancer)
    + add_stmt (Erubis::JavaGenerator)
    + add_stmt (Erubis::RubyGenerator)
    + add_stmt (Erubis::SchemeGenerator)
    + add_stmt (Erubis::JavascriptGenerator)
    + add_stmt (Erubis::NoCodeEnhancer)
    + add_stmt (Erubis::OptimizedGenerator)
    + add_stmt (Erubis::PhpGenerator)
    + add_stmt (Erubis::PerlGenerator)
    + add_stmt (Erubis::CppGenerator)
    + add_stmt (Erubis::CGenerator)
    + add_stmt (Erubis::Generator)
    + add_text (Erubis::CGenerator)
    + add_text (Erubis::Generator)
    + add_text (Erubis::InterpolationEnhancer)
    + add_text (Erubis::CppGenerator)
    + add_text (Erubis::PrintOutEnhancer)
    + add_text (Erubis::PerlGenerator)
    + add_text (Erubis::JavascriptGenerator)
    + add_text (Erubis::NoTextEnhancer)
    + add_text (Erubis::BiPatternEnhancer)
    + add_text (Erubis::NoCodeEnhancer)
    + add_text (Erubis::HeaderFooterEnhancer)
    + add_text (Erubis::PhpGenerator)
    + add_text (Erubis::PercentLineEnhancer)
    + add_text (Erubis::SchemeGenerator)
    + add_text (Erubis::PrefixedLineEnhancer)
    + add_text (Erubis::RubyGenerator)
    + add_text (Erubis::JavaGenerator)
    + add_text (Erubis::OptimizedGenerator)
    + compile (ActionView::TemplateHandlers::ErubisHandler)
    + compile (ActionView::TemplateHandlers::ErubisHandler)
    + compile (ActionView::TemplateHandlers::ErubisHandler)
    + convert (Erubis::HeaderFooterEnhancer)
    + convert (Erubis::Converter)
    + convert (Erubis::SimplifyEnhancer)
    + convert (Erubis::PI::TinyEruby)
    + convert (Erubis::PI::Converter)
    + convert (Erubis::TinyEruby)
    + convert! (Erubis::Engine)
    + convert_input (Erubis::Converter)
    + convert_input (Erubis::Basic::Converter)
    + convert_input (Erubis::InterpolationEnhancer)
    + convert_input (Erubis::DeleteIndentEnhancer)
    + convert_input (Erubis::PI::Converter)
    + def_method (Erubis::RubyEvaluator)
    + detect_spaces_at_bol (Erubis::Converter)
    + each (Erubis::Context)
    + engine_class (Erubis::Helpers::RailsHelper)
    + engine_class= (Erubis::Helpers::RailsHelper)
    + escape_text (Erubis::RubyGenerator)
    + escape_text (Erubis::JavascriptGenerator)
    + escape_text (Erubis::SchemeGenerator)
    + escape_text (Erubis::OptimizedGenerator)
    + escape_text (Erubis::PerlGenerator)
    + escape_text (Erubis::Generator)
    + escape_text (Erubis::JavaGenerator)
    + escape_text (Erubis::CppGenerator)
    + escape_text (Erubis::PhpGenerator)
    + escape_text (Erubis::CGenerator)
    + escape_xml (Erubis::XmlHelper)
    + escape_xml2 (Erubis::XmlHelper)
    + escaped_expr (Erubis::CppGenerator)
    + escaped_expr (Erubis::CGenerator)
    + escaped_expr (Erubis::RubyGenerator)
    + escaped_expr (Erubis::Generator)
    + escaped_expr (Erubis::SchemeGenerator)
    + escaped_expr (Erubis::OptimizedGenerator)
    + evaluate (Erubis::TinyEruby)
    + evaluate (Erubis::PrintEnabledEnhancer)
    + evaluate (Erubis::PI::TinyEruby)
    + evaluate (Erubis::Evaluator)
    + evaluate (Erubis::RubyEvaluator)
    + execute (Erubis::Main)
    + h (Erubis::XmlHelper)
    + html_escape (Erubis::XmlHelper)
    + init_converter (Erubis::PI::Ephp)
    + init_converter (Erubis::PI::Converter)
    + init_converter (Erubis::PI::Escheme)
    + init_converter (Erubis::PI::Ecpp)
    + init_converter (Erubis::PI::Ejavascript)
    + init_converter (Erubis::PI::Ec)
    + init_converter (Erubis::PI::Eperl)
    + init_converter (Erubis::Converter)
    + init_converter (Erubis::OptimizedEruby)
    + init_converter (Erubis::PI::Eruby)
    + init_converter (Erubis::PI::Ejava)
    + init_converter (Erubis::Basic::Converter)
    + init_evaluator (Erubis::Evaluator)
    + init_generator (Erubis::PrefixedLineEnhancer)
    + init_generator (Erubis::Generator)
    + init_generator (Erubis::SchemeGenerator)
    + init_generator (Erubis::JavaGenerator)
    + init_generator (Erubis::CGenerator)
    + init_generator (Erubis::JavascriptGenerator)
    + init_generator (Erubis::RubyGenerator)
    + init_generator (Erubis::CppGenerator)
    + init_generator (Erubis::PhpGenerator)
    + init_generator (Erubis::PerlGenerator)
    + init_generator (Erubis::OptimizedGenerator)
    + init_properties (Erubis::Helpers::RailsHelper)
    + init_properties= (Erubis::Helpers::RailsHelper)
    + keys (Erubis::Context)
    + load_file (Erubis::Engine)
    + main (Erubis::Main)
    + new (Erubis::Main)
    + new (Erubis::PreprocessingEruby)
    + new (Erubis::PI::TinyEruby)
    + new (Erubis::TinyEruby)
    + new (Erubis::Context)
    + new (Erubis::Engine)
    + new (Erubis::BiPatternEnhancer)
    + not_implemented (Kernel)
    + pattern_regexp (Erubis::Basic::Converter)
    + pp_check_box (Erubis::Helpers::RailsFormHelper)
    + pp_collection_select (Erubis::Helpers::RailsFormHelper)
    + pp_country_select (Erubis::Helpers::RailsFormHelper)
    + pp_error_on (Erubis::Helpers::RailsFormHelper)
    + pp_file_field (Erubis::Helpers::RailsFormHelper)
    + pp_form_tag (Erubis::Helpers::RailsFormHelper)
    + pp_hidden_field (Erubis::Helpers::RailsFormHelper)
    + pp_image_submit_tag (Erubis::Helpers::RailsFormHelper)
    + pp_password_field (Erubis::Helpers::RailsFormHelper)
    + pp_radio_button (Erubis::Helpers::RailsFormHelper)
    + pp_render_partial (Erubis::Helpers::RailsFormHelper)
    + pp_select (Erubis::Helpers::RailsFormHelper)
    + pp_submit_tag (Erubis::Helpers::RailsFormHelper)
    + pp_tag_helper (Erubis::Helpers::RailsFormHelper)
    + pp_template_filename (Erubis::Helpers::RailsFormHelper)
    + pp_template_filename (Erubis::Helpers::RailsFormHelper)
    + pp_text_area (Erubis::Helpers::RailsFormHelper)
    + pp_text_field (Erubis::Helpers::RailsFormHelper)
    + pp_time_zone_select (Erubis::Helpers::RailsFormHelper)
    + preprocessing (Erubis::Helpers::RailsHelper)
    + preprocessing= (Erubis::Helpers::RailsHelper)
    + print (Erubis::PrintEnabledEnhancer)
    + process (Erubis::Engine)
    + process_proc (Erubis::Engine)
    + result (Erubis::PI::TinyEruby)
    + result (Erubis::Evaluator)
    + result (Erubis::RubyEvaluator)
    + result (Erubis::TinyEruby)
    + show_src (Erubis::Helpers::RailsHelper)
    + show_src= (Erubis::Helpers::RailsHelper)
    + switch_to_expr (Erubis::OptimizedGenerator)
    + switch_to_stmt (Erubis::OptimizedGenerator)
    + to_hash (Erubis::Context)
    + u (Erubis::XmlHelper)
    + update (Erubis::Context)
    + url_encode (Erubis::XmlHelper)
    +
    +
    + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/index.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/index.html new file mode 100644 index 0000000..8603883 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/index.html @@ -0,0 +1,24 @@ + + + + + + + RDoc Documentation + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/rdoc-style.css b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/rdoc-style.css new file mode 100644 index 0000000..44c7b3d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc-api/rdoc-style.css @@ -0,0 +1,208 @@ + +body { + font-family: Verdana,Arial,Helvetica,sans-serif; + font-size: 90%; + margin: 0; + margin-left: 40px; + padding: 0; + background: white; +} + +h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } +h1 { font-size: 150%; } +h2,h3,h4 { margin-top: 1em; } + +a { background: #eef; color: #039; text-decoration: none; } +a:hover { background: #039; color: #eef; } + +/* Override the base stylesheet's Anchor inside a table cell */ +td > a { + background: transparent; + color: #039; + text-decoration: none; +} + +/* and inside a section title */ +.section-title > a { + background: transparent; + color: #eee; + text-decoration: none; +} + +/* === Structural elements =================================== */ + +div#index { + margin: 0; + margin-left: -40px; + padding: 0; + font-size: 90%; +} + + +div#index a { + margin-left: 0.7em; +} + +div#index .section-bar { + margin-left: 0px; + padding-left: 0.7em; + background: #ccc; + font-size: small; +} + + +div#classHeader, div#fileHeader { + width: auto; + color: white; + padding: 0.5em 1.5em 0.5em 1.5em; + margin: 0; + margin-left: -40px; + border-bottom: 3px solid #006; +} + +div#classHeader a, div#fileHeader a { + background: inherit; + color: white; +} + +div#classHeader td, div#fileHeader td { + background: inherit; + color: white; +} + + +div#fileHeader { + background: #057; +} + +div#classHeader { + background: #048; +} + + +.class-name-in-header { + font-size: 180%; + font-weight: bold; +} + + +div#bodyContent { + padding: 0 1.5em 0 1.5em; +} + +div#description { + padding: 0.5em 1.5em; + background: #efefef; + border: 1px dotted #999; +} + +div#description h1,h2,h3,h4,h5,h6 { + color: #125;; + background: transparent; +} + +div#validator-badges { + text-align: center; +} +div#validator-badges img { border: 0; } + +div#copyright { + color: #333; + background: #efefef; + font: 0.75em sans-serif; + margin-top: 5em; + margin-bottom: 0; + padding: 0.5em 2em; +} + + +/* === Classes =================================== */ + +table.header-table { + color: white; + font-size: small; +} + +.type-note { + font-size: small; + color: #DEDEDE; +} + +.xxsection-bar { + background: #eee; + color: #333; + padding: 3px; +} + +.section-bar { + color: #333; + border-bottom: 1px solid #999; + margin-left: -20px; +} + + +.section-title { + background: #79a; + color: #eee; + padding: 3px; + margin-top: 2em; + margin-left: -30px; + border: 1px solid #999; +} + +.top-aligned-row { vertical-align: top } +.bottom-aligned-row { vertical-align: bottom } + +/* --- Context section classes ----------------------- */ + +.context-row { } +.context-item-name { font-family: monospace; font-weight: bold; color: black; } +.context-item-value { font-size: small; color: #448; } +.context-item-desc { color: #333; padding-left: 2em; } + +/* --- Method classes -------------------------- */ +.method-detail { + background: #efefef; + padding: 0; + margin-top: 0.5em; + margin-bottom: 1em; + border: 1px dotted #ccc; +} +.method-heading { + color: black; + background: #ccc; + border-bottom: 1px solid #666; + padding: 0.2em 0.5em 0 0.5em; +} +.method-signature { color: black; background: inherit; } +.method-name { font-weight: bold; } +.method-args { font-style: italic; } +.method-description { padding: 0 0.5em 0 0.5em; } + +/* --- Source code sections -------------------- */ + +a.source-toggle { font-size: 90%; } +div.method-source-code { + background: #262626; + color: #ffdead; + margin: 1em; + padding: 0.5em; + border: 1px dashed #999; + overflow: hidden; +} + +div.method-source-code pre { color: #ffdead; overflow: hidden; } + +/* --- Ruby keyword styles --------------------- */ + +.standalone-code { background: #221111; color: #ffdead; overflow: hidden; } + +.ruby-constant { color: #7fffd4; background: transparent; } +.ruby-keyword { color: #00ffff; background: transparent; } +.ruby-ivar { color: #eedd82; background: transparent; } +.ruby-operator { color: #00ffee; background: transparent; } +.ruby-identifier { color: #ffdead; background: transparent; } +.ruby-node { color: #ffa07a; background: transparent; } +.ruby-comment { color: #b22222; font-weight: bold; background: transparent; } +.ruby-regexp { color: #ffa07a; background: transparent; } +.ruby-value { color: #7fffd4; background: transparent; } \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc/docstyle.css b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc/docstyle.css new file mode 100644 index 0000000..f05442d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc/docstyle.css @@ -0,0 +1,209 @@ +body { + background-color:#FFFFFF; +} + +.mainbody { + color:#333333; + line-height:150%; + margin: 5px 30px 5px 30px; +} + +a:link, a:active, a:hover { + color:#CC6600; +} + +a:visited { + color:#DD9900; +} + +p { + color:#333333; + line-height:150%; +} + +pre { + width: 100%; + line-height:130%; + white-space:pre; +} + +pre.program { + border-style:solid; + border-width:1px; + border-color:#6699FF; + color:#333333; + background-color:#DDEEFF; + padding:8px 9px 8px 9px; + margin:0px; + word-break:break-all; +} + +pre.terminal { + border-style:solid; + border-width:1; + border-color:#999999; + color:#333333; + background-color:#E0E0E0; + padding:9px 10px 9px 10px; + margin:0px; + word-break:break-all; +} + +pre.output { + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + color:#333333; + background-color:#FFFFFF; + padding:8px 9px 8px 9px; + margin:0px; + word-break:break-all; +} + + +pre strong { + color: #990000; + font-weight: bold; +} + + +.program_caption { + margin-top: 20px; +} + +.terminal_caption { + margin-top: 20px; +} + +.output_caption { + margin-top: 20px; +} + + +ul,ol,dl { + /* margin:0px; */ + /* padding:0px; */ + color:#333333; + line-height:140%; +} + +.dt2, .dt3 { + font-weight:bold; +} + +.table1 { + padding:2px; + color:#333333; + background-color:#DDDDCC; + line-height:130%; + /* + border-width:1px; + border-style:solid; + border-color:#FFFFFF; + */ + margin:5; +} + +.th1, .th2 { + padding:1px; + color:#333333; + /* background-color:#DDDDCC; */ + background-color:#CCCCBB; + line-height:130%; +} + +.td1, .th2 { + padding:1px; + color:#333333; + background-color:#EEEEDD; + line-height:130%; +} + +.caption1, .caption2 { + /* font-size:x-small; */ + color:#333333; +} + +.table2 { + padding:1px; + color:#333333; + background-color:#DDDDCC; + line-height:130%; + /* + border-width:1px; + border-style:solid; + border-color:#FFFFFF; + */ + margin:5; +} + +h1, .chapter, .doctitle { + color:#333333; + font-weight:bold; + padding:30px 0px 10px 0px; +} + +h2, .section { + color:#333333; + font-weight:bold; + border-style:solid; + border-color:#6699FF; + border-width:0px 0px 2px 30px; + padding:10px 20px 0px 5px; +} + +h3, .subsection { + color:#333333; + font-weight:bold; + border-style:solid; + border-color:#6699FF; + border-width: 0px 0px 0px 15px; + padding: 10px 20px 0px 5px; +} + +.em { + font-weight:bold; +} + +.toc { + /* font-size:small; */ + /* line-height:100%; */ +} + +.footnote { + font-size:small; +} + +div.note, div.tips { + background-color:#FFFFDD; + border-style:solid; + border-width:0px 1px 0px 1px; + border-color:#DDDD66; + color:#333300; + /* font-size:small; */ + line-height:120%; + margin-top: 10px; + padding: 5px 20px 5px 20px; +} + +div.note span.caption, div.tips span.caption { + color: #C60; +} + +.figure { + /* + border-width:1px; + border-color:#DDDD66; + white-space:pre; + */ +} + +strong { + color: #630; + font-weight; bold; +} + + +em { + font-style: italic; +} diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc/users-guide.html b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc/users-guide.html new file mode 100644 index 0000000..60cb672 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/doc/users-guide.html @@ -0,0 +1,3551 @@ + + + + + Erubis Users' Guide + + + + + + +
    +
    + +

    Erubis Users' Guide

    +

    release: 2.7.0 +

    + +

    Preface

    +

    Erubis is an implementation of eRuby. +It has the following features. +

    +
      +
    • Very fast, almost three times faster than ERB and about ten percent faster than eruby (implemented in C) +
    • +
    • File caching of converted Ruby script support +
    • +
    • Auto escaping support +
    • +
    • Auto trimming spaces around '<% %>' +
    • +
    • Embedded pattern changeable (default '<% %>') +
    • +
    • Enable to handle Processing Instructions (PI) as embedded pattern (ex. '<?rb ... ?>') +
    • +
    • Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) +
    • +
    • Context object available and easy to combine eRuby template with YAML datafile +
    • +
    • Print statement available +
    • +
    • Easy to expand and customize in subclass +
    • +
    • Ruby on Rails support +
    • +
    • mod_ruby support|#topcs-modruby +
    • +
    +

    Erubis is implemented in pure Ruby. It requires Ruby 1.8 or higher. +Erubis now supports Ruby 1.9. +

    + +

    Table of Contents

    + +
    + + +
    + + + +

    Installation

    +
      +
    • If you have installed RubyGems, just type gem install --remote erubis. +
      $ sudo gem install --remote erubis
      +
      +
    • +
    +
      +
    • Else install abstract at first, + and download erubis_X.X.X.tar.bz2 and install it by setup.rb. +
      $ tar xjf abstract_X.X.X.tar.bz2
      +$ cd abstract_X.X.X/
      +$ sudo ruby setup.rb
      +$ cd ..
      +$ tar xjf erubis_X.X.X.tar.bz2
      +$ cd erubis_X.X.X/
      +$ sudo ruby setup.rb
      +
      +
    • +
    +
      +
    • (Optional) 'contrib/inline-require' enables you to merge 'lib/**/*.rb' into 'bin/erubis'. +
      $ tar xjf erubis_X.X.X.tar.bz2
      +$ cd erubis_X.X.X/
      +$ unset RUBYLIB
      +$ contrib/inline-require -I lib bin/erubis > contrib/erubis
      +
      +
    • +
    +
    + + + +

    Tutorial

    + +

    Basic Example

    +

    Here is a basic example of Erubis. +

    + +
    +example1.eruby
    +
    <ul>
    +  <% for item in list %>
    +  <li><%= item %></li>
    +  <% end %>
    +  <%# here is ignored because starting with '#' %>
    +</ul>
    +
    + +
    +example1.rb
    +
    require 'erubis'
    +input = File.read('example1.eruby')
    +eruby = Erubis::Eruby.new(input)    # create Eruby object
    +
    +puts "---------- script source ---"
    +puts eruby.src                      # print script source
    +
    +puts "---------- result ----------"
    +list = ['aaa', 'bbb', 'ccc']
    +puts eruby.result(binding())        # get result
    +## or puts eruby.result(:list=>list)  # or pass Hash instead of Binding
    +
    +## # or
    +## eruby = Erubis::Eruby.new
    +## input = File.read('example1.eruby')
    +## src = eruby.convert(input)
    +## eval src
    +
    + +
    +output
    +
    $ ruby example1.rb
    +---------- script source ---
    +_buf = ''; _buf << '<ul>
    +';   for item in list 
    + _buf << '  <li>'; _buf << ( item ).to_s; _buf << '</li>
    +';   end 
    +
    + _buf << '</ul>
    +';
    +_buf.to_s
    +---------- result ----------
    +<ul>
    +  <li>aaa</li>
    +  <li>bbb</li>
    +  <li>ccc</li>
    +</ul>
    +
    +

    Erubis has command 'erubis'. Command-line option '-x' shows the compiled source code of eRuby script. +

    + +
    +example of command-line option '-x'
    +
    $ erubis -x example1.eruby
    +_buf = ''; _buf << '<ul>
    +';   for item in list 
    + _buf << '  <li>'; _buf << ( item ).to_s; _buf << '</li>
    +';   end 
    +
    + _buf << '</ul>
    +';
    +_buf.to_s
    +
    +
    + + + +

    Trimming Spaces

    +

    Erubis deletes spaces around '<% %>' automatically, while it leaves spaces around '<%= %>'. +

    + +
    +example2.eruby
    +
    <ul>
    +  <% for item in list %>      # trimmed
    +  <li>
    +    <%= item %>               # not trimmed
    +  </li>
    +  <% end %>                   # trimmed
    +</ul>
    +
    + +
    +compiled source code
    +
    $ erubis -x example2.eruby
    +_buf = ''; _buf << '<ul>
    +';   for item in list 
    + _buf << '  <li>
    +    '; _buf << ( item ).to_s; _buf << '
    +'; _buf << '  </li>
    +';   end 
    + _buf << '</ul>
    +';
    +_buf.to_s
    +
    +

    If you want leave spaces around '<% %>', add command-line property '--trim=false'. +

    + +
    +compiled source code with command-line property '--trim=false'
    +
    $ erubis -x --trim=false example2.eruby
    +_buf = ''; _buf << '<ul>
    +'; _buf << '  '; for item in list ; _buf << '
    +'; _buf << '  <li>
    +    '; _buf << ( item ).to_s; _buf << '
    +'; _buf << '  </li>
    +'; _buf << '  '; end ; _buf << '
    +'; _buf << '</ul>
    +';
    +_buf.to_s
    +
    +

    Or add option :trim=>false to Erubis::Eruby.new(). +

    + +
    +example2.rb
    +
    require 'erubis'
    +input = File.read('example2.eruby')
    +eruby = Erubis::Eruby.new(input, :trim=>false)
    +
    +puts "----- script source ---"
    +puts eruby.src                            # print script source
    +
    +puts "----- result ----------"
    +list = ['aaa', 'bbb', 'ccc']
    +puts eruby.result(binding())              # get result
    +
    + +
    +output
    +
    $ ruby example2.rb
    +----- script source ---
    +_buf = ''; _buf << '<ul>
    +'; _buf << '  '; for item in list ; _buf << '
    +'; _buf << '  <li>
    +    '; _buf << ( item ).to_s; _buf << '
    +'; _buf << '  </li>
    +'; _buf << '  '; end ; _buf << '
    +'; _buf << '</ul>
    +';
    +_buf.to_s
    +----- result ----------
    +<ul>
    +  
    +  <li>
    +    aaa
    +  </li>
    +  
    +  <li>
    +    bbb
    +  </li>
    +  
    +  <li>
    +    ccc
    +  </li>
    +  
    +</ul>
    +
    +
    + + + +

    Escape

    +

    Erubis has ability to escape (sanitize) expression. +Erubis::Eruby class act as the following: +

    +
      +
    • <%= expr %> - not escaped. +
    • +
    • <%== expr %> - escaped. +
    • +
    • <%=== expr %> - out to $stderr. +
    • +
    • <%==== expr %> - ignored. +
    • +
    +

    Erubis::EscapedEruby(*1) class handle '<%= %>' as escaped and '<%== %>' as not escaped. +It means that using Erubis::EscapedEruby you can escape expression by default. +Also Erubis::XmlEruby class (which is equivalent to Erubis::EscapedEruby) is provided for compatibility with Erubis 1.1. +

    + +
    +example3.eruby
    +
    <% for item in list %>
    +  <p><%= item %></p>
    +  <p><%== item %></p>
    +  <p><%=== item %></p>
    +
    +<% end %>
    +
    + +
    +example3.rb
    +
    require 'erubis'
    +input = File.read('example3.eruby')
    +eruby = Erubis::EscapedEruby.new(input)    # or Erubis::XmlEruby
    +
    +puts "----- script source ---"
    +puts eruby.src                             # print script source
    +
    +puts "----- result ----------"
    +list = ['<aaa>', 'b&b', '"ccc"']
    +puts eruby.result(binding())               # get result
    +
    + +
    +output
    +
    $ ruby example3.rb 2> stderr.log
    +----- script source ---
    +_buf = ''; for item in list 
    + _buf << '  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; $stderr.puts("*** debug: item=#{(item).inspect}"); _buf << '</p>
    +
    +'; end 
    +_buf.to_s
    +----- result ----------
    +  <p>&lt;aaa&gt;</p>
    +  <p><aaa></p>
    +  <p></p>
    +
    +  <p>b&amp;b</p>
    +  <p>b&b</p>
    +  <p></p>
    +
    +  <p>&quot;ccc&quot;</p>
    +  <p>"ccc"</p>
    +  <p></p>
    +
    +$ cat stderr.log
    +*** debug: item="<aaa>"
    +*** debug: item="b&b"
    +*** debug: item="\"ccc\""
    +
    +

    The command-line option '-e' will do the same action as Erubis::EscapedEruby. +This option is available for any language. +

    + +
    $ erubis -l ruby -e example3.eruby
    +_buf = ''; for item in list 
    + _buf << '  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; $stderr.puts("*** debug: item=#{(item).inspect}"); _buf << '</p>
    +
    +'; end 
    +_buf.to_s
    +
    +

    Escaping function (default 'Erubis::XmlHelper.escape_xml()') can be changed by command-line property '--escapefunc=xxx' or by overriding Erubis::Eruby#escaped_expr() in subclass. +

    +
    +example to override Erubis::Eruby#escaped_expr()
    +
    class CGIEruby < Erubis::Eruby
    +  def escaped_expr(code)
    +    return "CGI.escapeHTML((#{code.strip}).to_s)"
    +    #return "h(#{code.strip})"
    +  end
    +end
    +
    +class LatexEruby < Erubi::Eruby
    +  def escaped_expr(code)
    +    return "(#{code}).gsub(/[%\\]/,'\\\\\&')"
    +  end
    +end
    +
    +
    +
    +
    (*1)
    +
    Erubis::EscapedEruby class includes Erubis::EscapeEnhancer which swtches the action of '<%= %>' and '<%== %>'.
    +
    +
    +
    + + + +

    Embedded Pattern

    +

    You can change embedded pattern '<% %>' to another by command-line option '-p' or option ':pattern=>...' of Erubis::Eruby.new(). +

    + +
    +example4.eruby
    +
    <!--% for item in list %-->
    +  <p><!--%= item %--></p>
    +<!--% end %-->
    +
    + +
    +compiled source code with command-line option '-p'
    +
    $ erubis -x -p '<!--% %-->' example4.eruby
    +_buf = ''; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +'; end 
    +_buf.to_s
    +
    + +
    +example4.rb
    +
    require 'erubis'
    +input = File.read('example4.eruby')
    +eruby = Erubis::Eruby.new(input, :pattern=>'<!--% %-->')
    +                                      # or '<(?:!--)?% %(?:--)?>'
    +
    +puts "---------- script source ---"
    +puts eruby.src                            # print script source
    +
    +puts "---------- result ----------"
    +list = ['aaa', 'bbb', 'ccc']
    +puts eruby.result(binding())              # get result
    +
    + +
    +output
    +
    $ ruby example4.rb
    +---------- script source ---
    +_buf = ''; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +'; end 
    +_buf.to_s
    +---------- result ----------
    +  <p>aaa</p>
    +  <p>bbb</p>
    +  <p>ccc</p>
    +
    +

    It is able to specify regular expression with :pattern option. +Notice that you must use '(?: )' instead of '( )' for grouping. +For example, '<(!--)?% %(--)?>' will not work while '<(?:!--)?% %(?:--)?>' will work. +

    +
    + + + +

    Context Object

    +

    Context object is a set of data which are used in eRuby script. +Using context object makes clear which data to be used. +In Erubis, Hash object and Erubis::Context object are available as context object. +

    +

    Context data can be accessible via instance variables in eRuby script. +

    + +
    +example5.eruby
    +
    <span><%= @val %></span>
    +<ul>
    + <% for item in @list %>
    +  <li><%= item %></li>
    + <% end %>
    +</ul>
    +
    + +
    +example5.rb
    +
    require 'erubis'
    +input = File.read('example5.eruby')
    +eruby = Erubis::Eruby.new(input)      # create Eruby object
    +
    +## create context object
    +## (key means var name, which may be string or symbol.)
    +context = {
    +  :val   => 'Erubis Example',
    +  'list' => ['aaa', 'bbb', 'ccc'],
    +}
    +## or
    +# context = Erubis::Context.new()
    +# context['val'] = 'Erubis Example'
    +# context[:list] = ['aaa', 'bbb', 'ccc'],
    +
    +puts eruby.evaluate(context)         # get result
    +
    + +
    +output
    +
    $ ruby example5.rb
    +<span>Erubis Example</span>
    +<ul>
    +  <li>aaa</li>
    +  <li>bbb</li>
    +  <li>ccc</li>
    +</ul>
    +
    +

    The difference between Erubis#result(binding) and Erubis#evaluate(context) is that the former invokes 'eval @src, binding' and the latter invokes 'context.instance_eval @src'. +This means that data is passed into eRuby script via local variables when Eruby::binding() is called, or passed via instance variables when Eruby::evaluate() is called. +

    +

    Here is the definition of Erubis#result() and Erubis#evaluate(). +

    +
    +definition of result(binding) and evaluate(context)
    +
    def result(_binding=TOPLEVEL_BINDING)
    +  if _binding.is_a?(Hash)
    +    # load hash data as local variable
    +    _h = _binding
    +    _binding = binding()
    +    eval _h.collect{|k,v| "#{k} = _h[#{k.inspect}];"}.join, _binding
    +  end
    +  return eval(@src, _binding)
    +end
    +
    +def evaluate(_context=Erubis::Context.new)
    +  if _context.is_a?(Hash)
    +    # convert hash object to Context object
    +    _hash = _context
    +    _context = Erubis::Context.new
    +    _hash.each {|k, v| _context[k] = v }
    +  end
    +  return _context.instance_eval(@src)
    +end
    +
    +

    instance_eval() is defined at Object class so it is able to use any object as a context object as well as Hash or Erubis::Context. +

    + +
    +example6.rb
    +
    class MyData
    +  attr_accessor :val, :list
    +end
    +
    +## any object can be a context object
    +mydata = MyData.new
    +mydata.val = 'Erubis Example'
    +mydata.list = ['aaa', 'bbb', 'ccc']
    +
    +require 'erubis'
    +eruby = Erubis::Eruby.new(File.read('example5.eruby'))
    +puts eruby.evaluate(mydata)
    +
    + +
    +output
    +
    $ ruby example6.rb
    +<span>Erubis Example</span>
    +<ul>
    +  <li>aaa</li>
    +  <li>bbb</li>
    +  <li>ccc</li>
    +</ul>
    +
    +

    It is recommended to use 'Erubis::Eruby#evaluate(context)' rather than 'Erubis::Eruby#result(binding())' because the latter has some problems. +See evaluate(context) v.s. result(binding) section for details. +

    +
    + + + +

    Context Data File

    +

    Command-line option '-f' specifies context data file. +Erubis load context data file and use it as context data. +Context data file can be YAML file ('*.yaml' or '*.yml') or Ruby script ('*.rb'). +

    + +
    +example7.eruby
    +
    <h1><%= @title %></h1>
    +<ul>
    + <% for user in @users %>
    +  <li>
    +    <a href="mailto:<%= user['mail']%>"><%= user['name'] %></a>
    +  </li>
    + <% end %>
    +</ul>
    +
    + +
    +context.yaml
    +
    title: Users List
    +users:
    +  - name:  foo
    +    mail:  foo@mail.com
    +  - name:  bar
    +    mail:  bar@mail.net
    +  - name:  baz
    +    mail:  baz@mail.org
    +
    + +
    +context.rb
    +
    @title = 'Users List'
    +@users = [
    +   { 'name'=>'foo', 'mail'=>'foo@mail.com' },
    +   { 'name'=>'bar', 'mail'=>'bar@mail.net' },
    +   { 'name'=>'baz', 'mail'=>'baz@mail.org' },
    +]
    +
    + +
    +example of command-line option '-f'
    +
    $ erubis -f context.yaml example7.eruby
    +<h1>Users List</h1>
    +<ul>
    +  <li>
    +    <a href="mailto:foo@mail.com">foo</a>
    +  </li>
    +  <li>
    +    <a href="mailto:bar@mail.net">bar</a>
    +  </li>
    +  <li>
    +    <a href="mailto:baz@mail.org">baz</a>
    +  </li>
    +</ul>
    +$ erubis -f context.rb example7.eruby
    +<h1>Users List</h1>
    +<ul>
    +  <li>
    +    <a href="mailto:foo@mail.com">foo</a>
    +  </li>
    +  <li>
    +    <a href="mailto:bar@mail.net">bar</a>
    +  </li>
    +  <li>
    +    <a href="mailto:baz@mail.org">baz</a>
    +  </li>
    +</ul>
    +
    +

    Command-line option '-S' converts keys of mapping in YAML data file from string into symbol. +Command-line option '-B' invokes 'Erubis::Eruby#result(binding())' instead of 'Erubis::Eruby#evaluate(context)'. +

    +
    + + + +

    Context Data String

    +

    Command-line option '-c str' enables you to specify context data in command-line. +str can be YAML flow-style or Ruby code. +

    + +
    +example8.eruby
    +
    <h1><%= @title %></h1>
    +<ul>
    +<% for item in @list %>
    + <li><%= item %></li>
    +<% end %>
    +</ul>
    +
    + +
    +example of YAML flow style
    +
    $ erubis -c '{title: Example, list: [AAA, BBB, CCC]}' example8.eruby
    +<h1>Example</h1>
    +<ul>
    + <li>AAA</li>
    + <li>BBB</li>
    + <li>CCC</li>
    +</ul>
    +
    + +
    +example of Ruby code
    +
    $ erubis -c '@title="Example"; @list=%w[AAA BBB CCC]' example8.eruby
    +<h1>Example</h1>
    +<ul>
    + <li>AAA</li>
    + <li>BBB</li>
    + <li>CCC</li>
    +</ul>
    +
    +
    + + + +

    Preamble and Postamble

    +

    The first line ('_buf = '';') in the compiled source code is called preamble +and the last line ('_buf.to_s') is called postamble. +

    +

    Command-line option '-b' skips the output of preamble and postamble. +

    + +
    +example9.eruby
    +
    <% for item in @list %>
    + <b><%= item %></b>
    +<% end %>
    +
    + +
    +compiled source code with and without command-line option '-b'
    +
    $ erubis -x example9.eruby
    +_buf = ''; for item in @list 
    + _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b>
    +'; end 
    +_buf.to_s
    +$ erubis -x -b example9.eruby
    + for item in @list 
    + _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b>
    +'; end 
    +
    +

    Erubis::Eruby.new option ':preamble=>false' and ':postamble=>false' also suppress output of preamble or postamle. +

    + +
    +example9.rb
    +
    require 'erubis'
    +input = File.read('example9.eruby')
    +eruby1 = Erubis::Eruby.new(input)
    +eruby2 = Erubis::Eruby.new(input, :preamble=>false, :postamble=>false)
    +
    +puts eruby1.src   # print preamble and postamble
    +puts "--------------"
    +puts eruby2.src   # don't print preamble and postamble
    +
    + +
    +output
    +
    $ ruby example9.rb
    +_buf = ''; for item in @list 
    + _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b>
    +'; end 
    +_buf.to_s
    +--------------
    + for item in @list 
    + _buf << ' <b>'; _buf << ( item ).to_s; _buf << '</b>
    +'; end 
    +
    +
    + + + +

    Processing Instruction (PI) Converter

    +

    Erubis can parse Processing Instructions (PI) as embedded pattern. +

    +
      +
    • '<?rb ... ?>' represents Ruby statement. +
    • +
    • '@{...}@' represents escaped expression value. +
    • +
    • '@!{...}@' represents normal expression value. +
    • +
    • '@!!{...}@' prints expression value to standard output. +
    • +
    • (experimental) '<%= ... %>' is also available to print expression value. +
    • +
    +

    This is more useful than basic embedded pattern ('<% ... >') because PI doesn't break XML or HTML at all. +For example the following XHTML file is well-formed and HTML validator got no errors on this example. +

    + +
    +example10.xhtml
    +
    <?xml version="1.0" ?>
    +<?rb
    +  lang = 'en'
    +  list = ['<aaa>', 'b&b', '"ccc"']
    +?>
    +<html lang="@!{lang}@">
    + <body>
    +  <ul>
    +  <?rb for item in list ?>
    +   <li>@{item}@</li>
    +  <?rb end ?>
    +  </ul>
    + </body>
    +</html>
    +
    +

    If the command-line property '--pi=name' is specified, erubis command parses input with PI converter. +If name is omitted then the following name is used according to '-l lang'. +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    '-l' optionPI name
    -l ruby<?rb ... ?>
    -l php<?php ... ?>
    -l perl<?perl ... ?>
    -l java<?java ... ?>
    -l javascript<?js ... ?>
    -l scheme<?scheme ... ?>
    +
    + +
    +output
    +
    $ erubis -x --pi example10.xhtml
    +_buf = ''; _buf << '<?xml version="1.0" ?>
    +';
    +  lang = 'en'
    +  list = ['<aaa>', 'b&b', '"ccc"']
    +
    + _buf << '<html lang="'; _buf << (lang).to_s; _buf << '">
    + <body>
    +  <ul>
    +';   for item in list 
    + _buf << '   <li>'; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '</li>
    +';   end 
    + _buf << '  </ul>
    + </body>
    +</html>
    +';
    +_buf.to_s
    +
    +

    Expression character can be changeable by command-line property '--embchar=char. Default is '@'. +

    +

    Use Erubis::PI::Eruby instead of Erubis::Eruby if you want to use PI as embedded pattern. +

    + +
    +example10.rb
    +
    require 'erubis'
    +input = File.read('example10.xhtml')
    +eruby = Erubis::PI::Eruby.new(input)
    +print eruby.src
    +
    + +
    +output
    +
    $ ruby example10.rb
    +_buf = ''; _buf << '<?xml version="1.0" ?>
    +';
    +  lang = 'en'
    +  list = ['<aaa>', 'b&b', '"ccc"']
    +
    + _buf << '<html lang="'; _buf << (lang).to_s; _buf << '">
    + <body>
    +  <ul>
    +';   for item in list 
    + _buf << '   <li>'; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '</li>
    +';   end 
    + _buf << '  </ul>
    + </body>
    +</html>
    +';
    +_buf.to_s
    +
    +

    (experimental) Erubis supports '<%= ... %>' pattern with PI pattern. +

    +
    +example of Rails view template
    +
    <table>
    +  <tr>
    +<?rb for item in @list ?>
    +    <td>@{item.id}@</td>
    +    <td>@{item.name}@</td>
    +    <td>
    +       <%= link_to 'Destroy', {:action=>'destroy', :id=>item.id},
    +                       :confirm=>'Are you OK?' %>
    +    </td>
    +<?rb end ?>
    +  </tr>
    +</table>
    +
    +
    + + + +

    Retrieve Ruby Code

    +

    Similar to '-x', ommand-line option '-X' shows converted Ruby source code. +The difference between '-x' and 'X' is that the former converts text part but the latter ignores it. +It means that you can retrieve Ruby code from eRuby script by '-X' option. +

    +

    For example, see the following eRuby script. +This is some complex, so it is difficult to grasp the program code. +

    + +
    +example11.rhtml
    +
    <?xml version="1.0" encoding="UTF-8"?>
    +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    +          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +  <body>
    +    <h3>List</h3>
    +    <% if @list.nil? || @list.empty? %>
    +    <p>not found.</p>
    +    <% else %>
    +    <table>
    +      <tbody>
    +        <% @list.each_with_index do |item, i| %>
    +        <tr bgcolor="<%= i % 2 == 0 ? '#FCC' : '#CCF' %>">
    +          <td><%= item %></td>
    +        </tr>
    +        <% end %>
    +      </tbody>
    +    </table>
    +    <% end %>
    +  </body>
    +</html>
    +
    +

    Command-line option '-X' extracts only the ruby code from eRuby script. +

    + +
    +result
    +
    $ erubis -X example11.rhtml
    +_buf = '';
    +
    +
    +
    +
    +
    +     if @list.nil? || @list.empty? 
    +
    +     else 
    +
    +
    +         @list.each_with_index do |item, i| 
    +                      _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
    +               _buf << ( item ).to_s;
    +
    +         end 
    +
    +
    +     end 
    +
    +
    +_buf.to_s
    +
    +

    Command-line option '-C' (cmpact) deletes empty lines. +

    + +
    +result
    +
    $ erubis -XC example11.rhtml
    +_buf = '';
    +     if @list.nil? || @list.empty? 
    +     else 
    +         @list.each_with_index do |item, i| 
    +                      _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
    +               _buf << ( item ).to_s;
    +         end 
    +     end 
    +_buf.to_s
    +
    +

    Option '-U' (unique) converts empty lines into a line. +

    + +
    +result
    +
    $ erubis -XU example11.rhtml
    +_buf = '';
    +
    +     if @list.nil? || @list.empty? 
    +
    +     else 
    +
    +         @list.each_with_index do |item, i| 
    +                      _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
    +               _buf << ( item ).to_s;
    +
    +         end 
    +
    +     end 
    +
    +_buf.to_s
    +
    +

    Option '-N' (number) adds line number. +It is available with '-C' or '-U'. +

    + +
    +result
    +
    $ erubis -XNU example11.rhtml
    +    1:  _buf = '';
    +
    +    7:       if @list.nil? || @list.empty? 
    +
    +    9:       else 
    +
    +   12:           @list.each_with_index do |item, i| 
    +   13:                        _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s;
    +   14:                 _buf << ( item ).to_s;
    +
    +   16:           end 
    +
    +   19:       end 
    +
    +   22:  _buf.to_s
    +
    +

    Command-line option '-X' is available with PHP script. +

    + +
    +example11.php
    +
    <?xml version="1.0"?>
    +<html>
    +  <body>
    +    <h3>List</h3>
    +    <?php if (!$list) { ?>
    +    <p>not found.</p>
    +    <?php } else { ?>
    +    <table>
    +      <tbody>
    +        <?php $i = 0; ?>
    +        <?php foreach ($list as $item) { ?>
    +        <tr bgcolor="<?php echo ++$i % 2 == 1 ? '#FCC' : '#CCF'; ?>">
    +          <td><?php echo $item; ?></td>
    +        </tr>
    +        <?php } ?>
    +      </tbody>
    +    </table>
    +    <?php } ?>
    +  </body>
    +</html>
    +
    + +
    +result
    +
    $ erubis -XNU -l php --pi=php --trim=false example11.php
    +
    +    5:      <?php if (!$list) { ?>
    +
    +    7:      <?php } else { ?>
    +
    +   10:          <?php $i = 0; ?>
    +   11:          <?php foreach ($list as $item) { ?>
    +   12:                       <?php echo ++$i % 2 == 1 ? '#FCC' : '#CCF'; ?>
    +   13:                <?php echo $item; ?>
    +
    +   15:          <?php } ?>
    +
    +   18:      <?php } ?>
    +
    +
    +
    + + +
    + + + +

    Enhancer

    +

    Enhancer is a module to add a certain feature into Erubis::Eruby class. +Enhancer may be language-independent or only for Erubis::Eruby class. +

    +

    To use enhancers, define subclass and include them. +The folloing is an example to use EscapeEnhancer, PercentLineEnhancer, and BiPatternEnhancer. +

    +
    class MyEruby < Erubis::Eruby
    +  include EscapeEnhancer
    +  include PercentLineEnhancer
    +  include BiPatternEnhancer
    +end
    +
    +

    You can specify enhancers in command-line with option '-E'. +The following is an example to use some enhancers in command-line. +

    +
    $ erubis -xE Escape,PercentLine,BiPattern example.eruby
    +
    +

    The following is the list of enhancers. +

    +
    +
    +EscapeEnhander (language-independent)
    +
    + Switch '<%= %>' to escaped and '<%== %>' to unescaped. +
    +
    +StdoutEnhancer (only for Eruby)
    +
    + Use $stdout instead of array buffer. +
    +
    +PrintOutEnhancer (only for Eruby)
    +
    + Use "print(...)" statement insead of "_buf << ...". +
    +
    +PrintEnabledEnhancer (only for Eruby)
    +
    + Enable to use print() in '<% ... %>'. +
    +
    +ArrayEnhancer (only for Eruby)
    +
    + Return array of string instead of returning string. +
    +
    +ArrayBufferEnhancer (only for Eruby)
    +
    + Use array buffer. It is a little slower than StringBufferEnhancer. +
    +
    +StringBufferEnhancer (only for Eruby)
    +
    + Use string buffer. This is included in Erubis::Eruby by default. +
    +
    +ErboutEnhancer (only for Eruby)
    +
    + Set '_erbout = _buf = "";' to be compatible with ERB. +
    +
    +NoTextEnhancer (language-independent)
    +
    + Print embedded code only and ignore normal text. +
    +
    +NoCodeEnhancer (language-independent)
    +
    + Print normal text only and ignore code. +
    +
    +SimplifyEnhancer (language-independent)
    +
    + Make compile faster but don't trim spaces around '<% %>'. +
    +
    +BiPatternEnhancer (language-independent)
    +
    + [experimental] Enable to use another embedded pattern with '<% %>'. +
    +
    +PercentLineEnhancer (language-independent)
    +
    + Regard lines starting with '%' as Ruby code. This is for compatibility with eruby and ERB. +
    +
    +HeaderFooterEnhancer (language-independent)
    +
    + [experimental] Enable you to add header and footer in eRuby script. +
    +
    +InterpolationEnhancer (only for Eruby)
    +
    + [experimental] convert '<p><%= text %></p>' into '_buf << %Q`<p>#{text}</p>`'. +
    +
    +DeleteIndentEnhancer (language-independent)
    +
    + [experimental] delete indentation of HTML file and eliminate page size. +
    +
    +

    If you required 'erubis/engine/enhanced', Eruby subclasses which include each enhancers are defined. +For example, class BiPatternEruby includes BiPatternEnhancer. +

    + +

    EscapeEnhancer

    +

    EscapeEnhancer switches '<%= ... %>' to escaped and '<%== ... %>' to unescaped. +

    + +
    +example.eruby
    +
    <div>
    +<% for item in list %>
    +  <p><%= item %></p>
    +  <p><%== item %></p>
    +<% end %>
    +</div>
    +
    + +
    +compiled source code
    +
    $ erubis -xE Escape example.eruby
    +_buf = ''; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf.to_s
    +
    +

    EscapeEnhancer is language-independent. +

    +
    + + + +

    StdoutEnhancer

    +

    StdoutEnhancer use $sdtdout instead of array buffer. +Therefore, you can use 'print' statement in embedded ruby code. +

    + +
    +compiled source code
    +
    $ erubis -xE Stdout example.eruby
    +_buf = $stdout; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +''
    +
    +

    StdoutEnhancer is only for Eruby. +

    +
    + + + +

    PrintOutEnhancer

    +

    PrintOutEnhancer makes compiled source code to use 'print(...)' instead of '_buf << ...'. +

    + +
    +compiled source code
    +
    $ erubis -xE PrintOut example.eruby
    + print '<div>
    +'; for item in list 
    + print '  <p>'; print(( item ).to_s); print '</p>
    +  <p>'; print Erubis::XmlHelper.escape_xml( item ); print '</p>
    +'; end 
    + print '</div>
    +';
    +
    +

    PrintOutEnhancer is only for Eruby. +

    +
    + + + +

    PrintEnabledEnhancer

    +

    PrintEnabledEnhancer enables you to use print() method in '<% ... %>'. +

    + +
    +printenabled-example.eruby
    +
    <% for item in @list %>
    +  <b><% print item %></b>
    +<% end %>
    +
    + +
    +printenabled-example.rb
    +
    require 'erubis'
    +class PrintEnabledEruby < Erubis::Eruby
    +  include Erubis::PrintEnabledEnhancer
    +end
    +input = File.read('printenabled-example.eruby')
    +eruby = PrintEnabledEruby.new(input)
    +list = ['aaa', 'bbb', 'ccc']
    +print eruby.evaluate(:list=>list)
    +
    + +
    +output result
    +
    $ ruby printenabled-example.rb
    +  <b>aaa</b>
    +  <b>bbb</b>
    +  <b>ccc</b>
    +
    +

    Notice to use Eruby#evaluate() and not to use Eruby#result(), +because print() method in '<% ... %>' invokes not Kernel#print() but PrintEnabledEnhancer#print(). +

    +

    PrintEnabledEnhancer is only for Eruby. +

    +
    + + + +

    ArrayEnhancer

    +

    ArrayEnhancer makes Eruby to return an array of strings. +

    + +
    +compiled source code
    +
    $ erubis -xE Array example.eruby
    +_buf = []; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf
    +
    +

    ArrayEnhancer is only for Eruby. +

    +
    + + + +

    ArrayBufferEnhancer

    +

    ArrayBufferEnhancer makes Eruby to use array buffer. +Array buffer is a litte slower than String buffer. +

    +

    ArrayBufferEnhancer is only for Eruby. +

    + +
    +compiled source code
    +
    $ erubis -xE ArrayBuffer example.eruby
    +_buf = []; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf.join
    +
    +
    + + + +

    StringBufferEnhancer

    +

    StringBufferEnhancer makes Eruby to use string buffer. +String buffer is a little faster than array buffer. +Erubis::Eruby includes this enhancer by default. +

    + +
    +compiled source code
    +
    $ erubis -xE StringBuffer example.eruby
    +_buf = ''; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf.to_s
    +
    +

    StringBufferEnhancer is only for Eruby. +

    +
    + + + +

    ErboutEnhancer

    +

    ErboutEnhancer makes Eruby to be compatible with ERB. +This is useful especially for Ruby on Rails. +

    +
    +compiled source code
    +
    $ erubis -xE Erbout example.eruby
    +_erbout = _buf = ''; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf.to_s
    +
    +

    ErboutEnhancer is only for Eruby. +

    +
    + + + +

    NoTextEnhancer

    +

    NoTextEnhancer suppress output of text and prints only embedded code. +This is useful especially when debugging a complex eRuby script. +

    + +
    +notext-example.eruby
    +
    <h3>List</h3>
    +<% if !@list || @list.empty? %>
    +<p>not found.</p>
    +<% else %>
    +<table>
    +  <tbody>
    +    <% @list.each_with_index do |item, i| %>
    +    <tr bgcolor="<%= i%2 == 0 ? '#FFCCCC' : '#CCCCFF' %>">
    +      <td><%= item %></td>
    +    </tr>
    +    <% end %>
    +  </tbody>
    +</table>
    +<% end %>
    +
    + +
    +output example of NoTextEnhancer
    +
    $ erubis -xE NoText notext-example.eruby
    +_buf = '';
    + if !@list || @list.empty? 
    +
    + else 
    +
    +
    +     @list.each_with_index do |item, i| 
    +                  _buf << ( i%2 == 0 ? '#FFCCCC' : '#CCCCFF' ).to_s;
    +           _buf << ( item ).to_s;
    +
    +     end 
    +
    +
    + end 
    +_buf.to_s
    +
    +

    NoTextEnhancer is language-independent. It is useful even if you are PHP user, see this section. +

    +
    + + + +

    NoCodeEnhancer

    +

    NoCodeEnhancer suppress output of embedded code and prints only normal text. +This is useful especially when validating HTML tags. +

    + +
    +nocode-example.eruby
    +
    <h3>List</h3>
    +<% if !@list || @list.empty? %>
    +<p>not found.</p>
    +<% else %>
    +<table>
    +  <tbody>
    +    <% @list.each_with_index do |item, i| %>
    +    <tr bgcolor="<%= i%2 == 0 ? '#FFCCCC' : '#CCCCFF' %>">
    +      <td><%= item %></td>
    +    </tr>
    +    <% end %>
    +  </tbody>
    +</table>
    +<% end %>
    +
    + +
    +output example of NoCodeEnhancer
    +
    $ erubis -xE NoCode notext-example.eruby
    +<h3>List</h3>
    +
    +<p>not found.</p>
    +
    +<table>
    +  <tbody>
    +
    +    <tr bgcolor="">
    +      <td></td>
    +    </tr>
    +
    +  </tbody>
    +</table>
    +
    +
    +

    NoCodeEnhancer is language-independent. It is useful even if you are PHP user, see this section. +

    +
    + + + +

    SimplifyEnhancer

    +

    SimplifyEnhancer makes compiling a little faster but don't trim spaces around '<% %>'. +

    + +
    +compiled source code
    +
    $ erubis -xE Simplify example.eruby
    +_buf = ''; _buf << '<div>
    +'; for item in list ; _buf << '
    +  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end ; _buf << '
    +</div>
    +';
    +_buf.to_s
    +
    +

    SimplifyEnhancer is language-independent. +

    +
    + + + +

    BiPatternEnhancer

    +

    BiPatternEnhancer enables to use another embedded pattern with '<% %>'. +By Default, '[= ... =]' is available for expression. +You can specify pattern by :bipattern property. +

    + +
    +bipattern-example.rhtml
    +
    <% for item in list %>
    +  <b>[= item =]</b>
    +  <b>[== item =]</b>
    +<% end %>
    +
    + +
    +compiled source code
    +
    $ erubis -xE BiPattern bipattern-example.rhtml
    +_buf = ''; for item in list 
    + _buf << '  <b>'; _buf << ( item ).to_s; _buf << '</b>
    +  <b>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</b>
    +'; end 
    +_buf.to_s
    +
    +

    BiPatternEnhancer is language-independent. +

    +
    + + + +

    PercentLineEnhancer

    +

    PercentLineEnhancer regards lines starting with '%' as Ruby code. +This is for compatibility with eruby and ERB. +

    + +
    +percentline-example.rhtml
    +
    <ul>
    +% for item in list
    +  <li><%= item %></li>
    +% end
    +</ul>
    +%% lines with '%%'
    +
    + +
    +compiled source code
    +
    $ erubis -xE PercentLine percentline-example.rhtml
    +_buf = ''; _buf << '<ul>
    +'; for item in list
    + _buf << '  <li>'; _buf << ( item ).to_s; _buf << '</li>
    +'; end
    + _buf << '</ul>
    +% lines with \'%%\'
    +';
    +_buf.to_s
    +
    +

    PercentLineEnhancer is language-independent. +

    +
    + + + +

    PrefixedLineEnhancer

    +

    PrefixedlineEnhancer regards lines starting with '%' as Ruby code. +It is similar to PercentLineEnhancer, but there are some differences. +

    +
      +
    • PrefixedlineEnhancer allows to indent lines starting with '%', but PercentLineEnhancer doesn't. +
    • +
    • PrefixedlineEnhancer allows to change prefixed character (default '%'), but PercentLineEnhancer doesn't. +
    • +
    + +
    +prefixedline-example.rhtml
    +
    <ul>
    +  ! for item in list
    +  <li><%= item %></li>
    +  ! end
    +</ul>
    +  !! lines with '!!'
    +
    + +
    +prefixedline-example.rb
    +
    require 'erubis'
    +
    +class PrefixedLineEruby < Erubis::Eruby
    +  include Erubis::PrefixedLineEnhancer
    +end
    +
    +input = File.read('prefixedline-example.rhtml')
    +eruby = PrefixedLineEruby.new(input, :prefixchar=>'!')  # default '%'
    +print eruby.src
    +
    + +
    +compiled source code
    +
    $ ruby prefixedline-example.rb
    +_buf = ''; _buf << '<ul>
    +';   for item in list
    + _buf << '  <li>'; _buf << ( item ).to_s; _buf << '</li>
    +';   end
    + _buf << '</ul>
    +  ! lines with \'!!\'
    +';
    +_buf.to_s
    +
    +

    PrefixedLineEnhancer is language-independent. +

    +
    + + + +

    HeaderFooterEnhancer

    +

    [experimental] +

    +

    HeaderFooterEnhancer enables you to add header and footer in eRuby script. +

    + +
    +headerfooter-example.eruby
    +
    <!--#header:
    +def list_items(items)
    +#-->
    +<% for item in items %>
    +  <b><%= item %></b>
    +<% end %>
    +<!--#footer:
    +end
    +#-->
    +
    + +
    +compiled source code
    +
    $ erubis -xE HeaderFooter headerfooter-example.eruby
    +
    +def list_items(items)
    +
    +_buf = ''; for item in items 
    + _buf << '  <b>'; _buf << ( item ).to_s; _buf << '</b>
    +'; end 
    +_buf.to_s
    +
    +end
    +
    +
    +

    Compare to the following: +

    + +
    +normal-eruby-test.eruby
    +
    <%
    +def list_items(items)
    +%>
    +<% for item in items %>
    +<li><%= item %></li>
    +<% end %>
    +<%
    +end
    +%>
    +
    + +
    +compiled source code
    +
    $ erubis -x normal-eruby-test.eruby
    +_buf = '';
    +def list_items(items)
    +
    + for item in items 
    + _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
    +'; end 
    +
    +end
    +
    +_buf.to_s
    +
    +

    Header and footer can be in any position in eRuby script, +that is, header is no need to be in the head of eRuby script. +

    + +
    +headerfooter-example2.rhtml
    +
    <?xml version="1.0"?>
    +<html>
    +<!--#header:
    +def page(list)
    +#-->
    + :
    +<!--#footer:
    +end
    +#-->
    +</html>
    +
    + +
    +compiled source code
    +
    $ erubis -xE HeaderFooter headerfooter-example2.rhtml
    +
    +def page(list)
    +
    +_buf = ''; _buf << '<?xml version="1.0"?>
    +<html>
    +'; _buf << ' :
    +'; _buf << '</html>
    +';
    +_buf.to_s
    +
    +end
    +
    +
    +

    HeaderFooterEnhancer is experimental and is language-independent. +

    +
    + + + +

    InterpolationEnhancer

    +

    [experimental] +

    +

    InterpolationEnhancer converts "<h1><%= title %></h1>" into +"_buf << %Q`<h1>#{ title }</h1>`". +This makes Eruby a litter faster because method call of String#<< are eliminated +by expression interpolations. +

    +
    +InterpolationEnhancer elmininates method call of String#<<.
    +
    ## Assume that input is '<a href="<%=url%>"><%=name%></a>'.
    +## Eruby convert input into the following code.  String#<< is called 5 times.
    +_buf << '<a href="'; _buf << (url).to_s; _buf << '">'; _buf << (name).to_s; _buf << '</a>';
    +
    +## If InterpolationEnhancer is used, String#<< is called only once.
    +_buf << %Q`<a href="#{url}">#{name}</a>`;
    +
    + +
    +compiled source code
    +
    $ erubis -xE Interpolation example.eruby
    +_buf = ''; _buf << %Q`<div>\n`
    + for item in list 
    + _buf << %Q`  <p>#{ item }</p>
    +  <p>#{Erubis::XmlHelper.escape_xml( item )}</p>\n`
    + end 
    + _buf << %Q`</div>\n`
    +_buf.to_s
    +
    +

    Erubis provides Erubis::FastEruby class which includes InterpolationEnhancer. +You can use Erubis::FastEruby class instead of Erubis::Eruby class. +

    +

    InterpolationEnhancer is only for Eruby. +

    +
    + + + +

    DeleteIndentEnhancer

    +

    [experimental] +DeleteIndentEnhancer deletes indentation of HTML file. +

    + +
    +compiled source code
    +
    $ erubis -xE DeleteIndent example.eruby
    +_buf = ''; _buf << '<div>
    +'; for item in list 
    + _buf << '<p>'; _buf << ( item ).to_s; _buf << '</p>
    +<p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf.to_s
    +
    +

    Notice that DeleteIndentEnhancer isn't intelligent. +It deletes indentations even if they are in <PRE></PRE>. +

    +

    DeleteIndentEnhancer is language-independent. +

    +
    + + +
    + + + +

    Multi-Language Support

    +

    Erubis supports the following languages(*2): +

    + +
    +
    +
    (*2)
    +
    If you need template engine in pure PHP/Perl/JavaScript, try Tenjin (http://www.kuwata-lab.com/tenjin/). Tenjin is a very fast and full-featured template engine implemented in pure PHP/Perl/JavaScript.
    +
    +
    + +

    PHP

    + +
    +example.ephp
    +
    <?xml version="1.0"?>
    +<html>
    + <body>
    +  <p>Hello <%= $user %>!</p>
    +  <table>
    +   <tbody>
    +    <% $i = 0; %>
    +    <% foreach ($list as $item) { %>
    +    <%   $i++; %>
    +    <tr bgcolor="<%= $i % 2 == 0 ? '#FFCCCC' : '#CCCCFF' %>">
    +     <td><%= $i %></td>
    +     <td><%== $item %></td>
    +    </tr>
    +    <% } %>
    +   </tbody>
    +  </table>
    + </body>
    +</html>
    +
    + +
    +compiled source code
    +
    $ erubis -l php example.ephp
    +<<?php ?>?xml version="1.0"?>
    +<html>
    + <body>
    +  <p>Hello <?php echo $user; ?>!</p>
    +  <table>
    +   <tbody>
    +<?php     $i = 0; ?>
    +<?php     foreach ($list as $item) { ?>
    +<?php       $i++; ?>
    +    <tr bgcolor="<?php echo $i % 2 == 0 ? '#FFCCCC' : '#CCCCFF'; ?>">
    +     <td><?php echo $i; ?></td>
    +     <td><?php echo htmlspecialchars($item); ?></td>
    +    </tr>
    +<?php     } ?>
    +   </tbody>
    +  </table>
    + </body>
    +</html>
    +
    +
    + + + +

    C

    + +
    +example.ec
    +
    <%
    +#include <stdio.h>
    +
    +int main(int argc, char *argv[])
    +{
    +    int i;
    +
    +%>
    +<html>
    + <body>
    +  <p>Hello <%= "%s", argv[0] %>!</p>
    +  <table>
    +   <tbody>
    +    <% for (i = 1; i < argc; i++) { %>
    +    <tr bgcolor="<%= i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>">
    +      <td><%= "%d", i %></td>
    +      <td><%= "%s", argv[i] %></td>
    +    </tr>
    +    <% } %>
    +   </tbody>
    +  </table>
    + </body>
    +</html>
    +<%
    +    return 0; 
    +}
    +%>
    +
    + +
    +compiled source code
    +
    $ erubis -l c example.ec
    +#line 1 "example.ec"
    +
    +#include <stdio.h>
    +
    +int main(int argc, char *argv[])
    +{
    +    int i;
    +
    +
    +fputs("<html>\n"
    +      " <body>\n"
    +      "  <p>Hello ", stdout); fprintf(stdout, "%s", argv[0]); fputs("!</p>\n"
    +      "  <table>\n"
    +      "   <tbody>\n", stdout);
    +     for (i = 1; i < argc; i++) { 
    +fputs("    <tr bgcolor=\"", stdout); fprintf(stdout, i % 2 == 0 ? "#FFCCCC" : "#CCCCFF"); fputs("\">\n"
    +      "      <td>", stdout); fprintf(stdout, "%d", i); fputs("</td>\n"
    +      "      <td>", stdout); fprintf(stdout, "%s", argv[i]); fputs("</td>\n"
    +      "    </tr>\n", stdout);
    +     } 
    +fputs("   </tbody>\n"
    +      "  </table>\n"
    +      " </body>\n"
    +      "</html>\n", stdout);
    +
    +    return 0; 
    +}
    +
    +
    +
    + + + +

    C++

    + +
    +example.ecpp
    +
    <%
    +#include <string>
    +#include <iostream>
    +#include <sstream>
    +
    +int main(int argc, char *argv[])
    +{
    +    std::stringstream _buf;
    +%>
    +<html>
    + <body>
    +  <p>Hello <%= argv[0] %>!</p>
    +  <table>
    +   <tbody>
    +    <% for (int i = 1; i < argc; i++) { %>
    +    <tr bgcolor="<%= i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>">
    +      <td><%= i %></td>
    +      <td><%= argv[i] %></td>
    +    </tr>
    +    <% } %>
    +   </tbody>
    +  </table>
    + </body>
    +</html>
    +<%
    +    std::string output = _buf.str();
    +    std::cout << output;
    +    return 0; 
    +}
    +%>
    +
    + +
    +compiled source code
    +
    $ erubis -l cpp example.ecpp
    +#line 1 "example.ecpp"
    +
    +#include <string>
    +#include <iostream>
    +#include <sstream>
    +
    +int main(int argc, char *argv[])
    +{
    +    std::stringstream _buf;
    +
    +_buf << "<html>\n"
    +        " <body>\n"
    +        "  <p>Hello "; _buf << (argv[0]); _buf << "!</p>\n"
    +        "  <table>\n"
    +        "   <tbody>\n";
    +     for (int i = 1; i < argc; i++) { 
    +_buf << "    <tr bgcolor=\""; _buf << (i % 2 == 0 ? "#FFCCCC" : "#CCCCFF"); _buf << "\">\n"
    +        "      <td>"; _buf << (i); _buf << "</td>\n"
    +        "      <td>"; _buf << (argv[i]); _buf << "</td>\n"
    +        "    </tr>\n";
    +     } 
    +_buf << "   </tbody>\n"
    +        "  </table>\n"
    +        " </body>\n"
    +        "</html>\n";
    +
    +    std::string output = _buf.str();
    +    std::cout << output;
    +    return 0; 
    +}
    +
    +
    +
    + + + +

    Java

    + +
    +Example.ejava
    +
    <%
    +import java.util.*;
    +
    +public class Example {
    +  private String user;
    +  private String[] list;
    +  public example(String user, String[] list) {
    +    this.user = user;
    +    this.list = list;
    +  }
    +
    +  public String view() {
    +    StringBuffer _buf = new StringBuffer();
    +%>
    +<html>
    + <body>
    +  <p>Hello <%= user %>!</p>
    +  <table>
    +   <tbody>
    +    <% for (int i = 0; i < list.length; i++) { %>
    +    <tr bgcolor="<%= i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>">
    +     <td><%= i + 1 %></td>
    +     <td><%== list[i] %></td>
    +    </tr>
    +    <% } %>
    +   </tbody>
    +  </table>
    + <body>
    +</html>
    +<%
    +    return _buf.toString();
    +  }
    +
    +  public static void main(String[] args) {
    +    String[] list = { "<aaa>", "b&b", "\"ccc\"" };
    +    Example ex = Example.new("Erubis", list);
    +    System.out.print(ex.view());
    +  }
    +
    +  public static String escape(String s) {
    +    StringBuffer sb = new StringBuffer();
    +    for (int i = 0; i < s.length(); i++) {
    +      char ch = s.charAt(i);
    +      switch (ch) {
    +      case '<':   sb.append("&lt;"); break;
    +      case '>':   sb.append("&gt;"); break;
    +      case '&':   sb.append("&amp;"); break;
    +      case '"':   sb.append("&quot;"); break;
    +      default:    sb.append(ch);
    +      }
    +    }
    +    return sb.toString();
    +  }
    +}
    +%>
    +
    + +
    +compiled source code
    +
    $ erubis -b -l java example.ejava
    +
    +import java.util.*;
    +
    +public class Example {
    +  private String user;
    +  private String[] list;
    +  public example(String user, String[] list) {
    +    this.user = user;
    +    this.list = list;
    +  }
    +
    +  public String view() {
    +    StringBuffer _buf = new StringBuffer();
    +
    +_buf.append("<html>\n"
    +          + " <body>\n"
    +          + "  <p>Hello "); _buf.append(user); _buf.append("!</p>\n"
    +          + "  <table>\n"
    +          + "   <tbody>\n");
    +     for (int i = 0; i < list.length; i++) { 
    +_buf.append("    <tr bgcolor=\""); _buf.append(i % 2 == 0 ? "#FFCCCC" : "#CCCCFF"); _buf.append("\">\n"
    +          + "     <td>"); _buf.append(i + 1); _buf.append("</td>\n"
    +          + "     <td>"); _buf.append(escape(list[i])); _buf.append("</td>\n"
    +          + "    </tr>\n");
    +     } 
    +_buf.append("   </tbody>\n"
    +          + "  </table>\n"
    +          + " <body>\n"
    +          + "</html>\n");
    +
    +    return _buf.toString();
    +  }
    +
    +  public static void main(String[] args) {
    +    String[] list = { "<aaa>", "b&b", "\"ccc\"" };
    +    Example ex = Example.new("Erubis", list);
    +    System.out.print(ex.view());
    +  }
    +
    +  public static String escape(String s) {
    +    StringBuffer sb = new StringBuffer();
    +    for (int i = 0; i < s.length(); i++) {
    +      char ch = s.charAt(i);
    +      switch (ch) {
    +      case '<':   sb.append("&lt;"); break;
    +      case '>':   sb.append("&gt;"); break;
    +      case '&':   sb.append("&amp;"); break;
    +      case '"':   sb.append("&quot;"); break;
    +      default:    sb.append(ch);
    +      }
    +    }
    +    return sb.toString();
    +  }
    +}
    +
    +
    +
    + + + +

    Scheme

    + +
    +example.escheme
    +
    <html>
    + <body>
    +<%
    +(let ((user "Erubis")
    +      (items '("<aaa>" "b&b" "\"ccc\""))
    +      (i 0))
    + %>
    +  <p>Hello <%= user %>!</p>
    +  <table>
    +<%
    +  (for-each
    +   (lambda (item)
    +     (set! i (+ i 1))
    + %>
    +   <tr bgcolor="<%= (if (= (modulo i 2) 0) "#FFCCCC" "#CCCCFF") %>">
    +    <td><%= i %></td>
    +    <td><%= item %></td>
    +   </tr>
    +<%
    +   ) ; lambda end
    +   items) ; for-each end
    + %>
    +  </table>
    +<%
    +) ; let end
    +%>
    + </body>
    +</html>
    +
    + +
    +compiled source code
    +
    $ erubis -l scheme example.escheme
    +(let ((_buf '())) (define (_add x) (set! _buf (cons x _buf))) (_add "<html>
    + <body>\n")
    +
    +(let ((user "Erubis")
    +      (items '("<aaa>" "b&b" "\"ccc\""))
    +      (i 0))
    + 
    +(_add "  <p>Hello ")(_add user)(_add "!</p>
    +  <table>\n")
    +
    +  (for-each
    +   (lambda (item)
    +     (set! i (+ i 1))
    + 
    +(_add "   <tr bgcolor=\"")(_add (if (= (modulo i 2) 0) "#FFCCCC" "#CCCCFF"))(_add "\">
    +    <td>")(_add i)(_add "</td>
    +    <td>")(_add item)(_add "</td>
    +   </tr>\n")
    +
    +   ) ; lambda end
    +   items) ; for-each end
    + 
    +(_add "  </table>\n")
    +
    +) ; let end
    +
    +(_add " </body>
    +</html>\n")
    +  (reverse _buf))
    +
    + +
    +compiled source code (with --func=display property)
    +
    $ erubis -l scheme --func=display example.escheme
    +(display "<html>
    + <body>\n")
    +
    +(let ((user "Erubis")
    +      (items '("<aaa>" "b&b" "\"ccc\""))
    +      (i 0))
    + 
    +(display "  <p>Hello ")(display user)(display "!</p>
    +  <table>\n")
    +
    +  (for-each
    +   (lambda (item)
    +     (set! i (+ i 1))
    + 
    +(display "   <tr bgcolor=\"")(display (if (= (modulo i 2) 0) "#FFCCCC" "#CCCCFF"))(display "\">
    +    <td>")(display i)(display "</td>
    +    <td>")(display item)(display "</td>
    +   </tr>\n")
    +
    +   ) ; lambda end
    +   items) ; for-each end
    + 
    +(display "  </table>\n")
    +
    +) ; let end
    +
    +(display " </body>
    +</html>\n")
    +
    +
    + + + +

    Perl

    + +
    +example.eperl
    +
    <%
    +   my $user = 'Erubis';
    +   my @list = ('<aaa>', 'b&b', '"ccc"');
    +%>
    +<html>
    + <body>
    +  <p>Hello <%= $user %>!</p>
    +  <table>
    +   <% $i = 0; %>
    +   <% for $item (@list) { %>
    +   <tr bgcolor=<%= ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF' %>">
    +    <td><%= $i %></td>
    +    <td><%= $item %></td>
    +   </tr>
    +   <% } %>
    +  </table>
    + </body>
    +</html>
    +
    + +
    +compiled source code
    +
    $ erubis -l perl example.eperl
    +use HTML::Entities; 
    +   my $user = 'Erubis';
    +   my @list = ('<aaa>', 'b&b', '"ccc"');
    +
    +print('<html>
    + <body>
    +  <p>Hello '); print($user); print('!</p>
    +  <table>
    +');     $i = 0; 
    +    for $item (@list) { 
    +print('   <tr bgcolor='); print(++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF'); print('">
    +    <td>'); print($i); print('</td>
    +    <td>'); print($item); print('</td>
    +   </tr>
    +');     } 
    +print('  </table>
    + </body>
    +</html>
    +'); 
    +
    +
    + + + +

    JavaScript

    + +
    +example.ejs
    +
    <%
    +   var user = 'Erubis';
    +   var list = ['<aaa>', 'b&b', '"ccc"'];
    + %>
    +<html>
    + <body>
    +  <p>Hello <%= user %>!</p>
    +  <table>
    +   <tbody>
    +    <% var i; %>
    +    <% for (i = 0; i < list.length; i++) { %>
    +    <tr bgcolor="<%= i % 2 == 0 ? '#FFCCCC' : '#CCCCFF' %>">
    +     <td><%= i + 1 %></td>
    +     <td><%= list[i] %></td>
    +    </tr>
    +    <% } %>
    +   </tbody>
    +  </table>
    + </body>
    +</html>
    +
    + +
    +compiled source code
    +
    $ erubis -l js example.ejs
    +var _buf = [];
    +   var user = 'Erubis';
    +   var list = ['<aaa>', 'b&b', '"ccc"'];
    + 
    +_buf.push("<html>\n\
    + <body>\n\
    +  <p>Hello "); _buf.push(user); _buf.push("!</p>\n\
    +  <table>\n\
    +   <tbody>\n");
    +     var i; 
    +     for (i = 0; i < list.length; i++) { 
    +_buf.push("    <tr bgcolor=\""); _buf.push(i % 2 == 0 ? '#FFCCCC' : '#CCCCFF'); _buf.push("\">\n\
    +     <td>"); _buf.push(i + 1); _buf.push("</td>\n\
    +     <td>"); _buf.push(list[i]); _buf.push("</td>\n\
    +    </tr>\n");
    +     } 
    +_buf.push("   </tbody>\n\
    +  </table>\n\
    + </body>\n\
    +</html>\n");
    +document.write(_buf.join(""));
    +
    +

    If command-line option '--docwrite=false' is specified, +'_buf.join("");' is used instead of 'document.write(_buf.join(""));'. +This is useful when passing converted source code to eval() function in JavaScript. +

    +

    You can pass :docwrite=>false to Erubis::Ejavascript.new() in your Ruby script. +

    +
    s = File.read('example.jshtml')
    +engine = Erubis::Ejavascript.new(s, :docwrite=>false)
    +
    +

    If you want to specify any JavaScript code, use '--postamble=...'. +

    +

    Notice that default value of 'docwrite' property will be false in the future release. +

    +
    + + +
    + + + +

    Ruby on Rails Support

    +

    NOTICE: Rails 3 adopts Erubis as default default engine. You don't need to do anything at all when using Rails 3. This section is for Rails 2. +

    +

    Erubis supports Ruby on Rails. +This section describes how to use Erubis with Ruby on Rails. +

    + +

    Settings

    +

    Add the following code to your 'config/environment.rb' and restart web server. +This replaces ERB in Rails by Erubis entirely. +

    +
    +config/environment.rb
    +
    require 'erubis/helpers/rails_helper'
    +#Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby # or Erubis::FastEruby
    +#Erubis::Helpers::RailsHelper.init_properties = {}
    +#Erubis::Helpers::RailsHelper.show_src = nil
    +#Erubis::Helpers::RailsHelper.preprocessing = false
    +
    +

    Options: +

    +
    +
    +Erubis::Helpers::RailsHelper.engine_class (=Erubis::Eruby)
    +
    +

    Erubis engine class (default Erubis::Eruby). +

    +
    +
    +Erubis::Helpers::RailsHelper.init_properties (={})
    +
    +

    Optional arguments for Erubis::Eruby#initialize() method (default {}). +

    +
    +
    +Erubis::Helpers::RailsHelper.show_src (=nil)
    +
    +

    Whether to print converted Ruby code into log file. + If true, Erubis prints coverted code into log file. + If false, Erubis doesn't. + If nil, Erubis prints when ENV['RAILS_ENV'] == 'development'. + Default is nil. +

    +
    +
    +Erubis::Helpers::RailsHelper.preprocessing (=false)
    +
    +

    Enable preprocessing if true (default false). +

    +
    +
    +
    + + + +

    Preprosessing

    +

    Erubis supports preprocessing of template files. +Preprocessing make your Ruby on Rails application about 20-40 percent faster. +To enable preprocessing, set Erubis::Helpers::RailsHelper.preprocessing to true in your 'environment.rb' file. +

    +

    For example, assume the following template. +This is slow because link_to() method is called every time when template is rendered. +

    +
    <%= link_to 'Create', :action=>'create' %>
    +
    +

    The following is faster than the above, but not flexible because url is fixed. +

    +
    <a href="/users/create">Create</a>
    +
    +

    Preprocessing solves this problem. +If you use '[%= %]' instead of '<%= %>', preprocessor evaluate it only once when template is loaded. +

    +
    [%= link_to 'Create', :action=>'create'%]
    +
    +

    The above is evaluated by preprocessor and replaced to the following code automatically. +

    +
    <a href="/users/create">Create</a>
    +
    +

    Notice that this is done only once when template file is loaded. +It means that link_to() method is not called when template is rendered. +

    +

    If link_to() method have variable arguments, use _?() helper method. +

    +
    <% for user in @users %>
    +[%= link_to _?('user.name'), :action=>'show', :id=>_?('user.id') %]
    +<% end %>
    +
    +

    The above is evaluated by preprocessor when template is loaded and expanded into the following code. +This will be much faster because link_to() method is not called when rendering. +

    +
    <% for user in @users %>
    +<a href="/users/show/<%=user.id%>"><%=user.name%></a>
    +<% end %>
    +
    +

    Preprocessing statement ([% %]) is also available as well as preprocessing expression ([%= %]). +

    +
    <select name="state">
    +  <option value="">-</option>
    +[% for code in states.keys.sort %]
    +  <option value="[%= code %]">[%= states[code] %]</option>
    +[% end %]
    +</select>
    +
    +

    The above will be evaluated by preprocessor and expanded into the following when template is loaded. +In the result, rendering speed will be much faster because for-loop is not executed when rendering. +

    +
    <select name="state">
    +  <option value="">-</option>
    +  <option value="AK">Alaska</option>
    +  <option value="AL">Alabama</option>
    +  <option value="AR">Arkansas</option>
    +  <option value="AS">American Samoa</option>
    +  <option value="AZ">Arizona</option>
    +  <option value="CA">California</option>
    +  <option value="CO">Colorado</option>
    +   ....
    +</select>
    +
    +

    Notice that it is not recommended to use preprocessing with tag helpers, +because tag helpers generate different html code when form parameter has errors or not. +

    +

    Helper methods of Ruby on Rails are divided into two groups. +

    +
      +
    • link_to() or _() (method of gettext package) are not need to call for every time + as template is rendered because it returns same value when same arguments are passed. + These methods can be got faster by preprocessing. +
    • +
    • Tag helper methods should be called for every time as template is rendered + because it may return differrent value even if the same arguments are passed. + Preprocessing is not available with these methods. +
    • +
    +

    In Ruby on Rails 2.0, _?('user_id') is OK but _?('user.id') is NG +because the latter contains period ('.') character. +

    +
    <!-- NG in Rails 2.0, because _?('') contains period -->
    +[%= link_to 'Edit', edit_user_path(_?('@user.id')) %]
    +[%= link_to 'Show', @user %]
    +[%= link_to 'Delete', @user, :confirm=>'OK?', :method=>:delete %]
    +
    +<!-- OK in Rails 2.0 -->
    +<%= user_id = @user.id %>
    +[%= link_to 'Edit', edit_user_path(_?('user_id')) %]
    +[%= link_to 'Show', :action=>'show', :id=>_?('user_id') %]
    +[%= link_to 'Delete', {:action=>'destroy', :id=>_?('user_id')},
    +                      {:confirm=>'OK?', :method=>:delete} %]
    +
    +
    + + + +

    Form Helpers for Preprocessing

    +

    (Experimental) +

    +

    Erubis provides form helper methods for preprocessing. +These are defined in 'erubis/helpers/rails_form_helper.rb'. +If you want to use it, require it and include Erubis::Helpers::RailsFormHelper in 'app/helpers/applition_helper.rb' +

    +
    +app/helpers/xxx_helper.rb
    +
    require 'erubis/helpers/rails_form_helper'
    +module ApplicationHelper
    +  include Erubis::Helpers::RailsFormHelper
    +end
    +
    +

    Form helper methods defined in Erubis::Helpers::RailsFormHelper are named as 'pp_xxxx' +('pp' represents preprocessing). +

    +

    Assume the following view template: +

    +
    +_form.rhtml
    +
     <p>
    +  Name: <%= text_field :user, :name %>
    + </p>
    + <p>
    +  Name: [%= pp_text_field :user, :name %]
    + </p>
    +
    +

    Erubis preprocessor converts it to the following eRuby string: +

    +
    +preprocessed
    +
     <p>
    +  Name: <%= text_field :user, :name %>
    + </p>
    + <p>
    +  Name: <input id="stock_name" name="stock[name]" size="30" type="text" value="<%=h @stock.name%>" />
    + </p>
    +
    +

    Erubis converts it to the following Ruby code: +

    +
    +Ruby code
    +
     _buf << ' <p>
    +  Name: '; _buf << ( text_field :stock, :name ).to_s; _buf << '
    +'; _buf << ' </p>
    + <p>
    +  Name: <input id="stock_name" name="stock[name]" size="30" type="text" value="'; _buf << (h @stock.name).to_s; _buf << '" />
    + </p>
    +';
    +
    +

    The above Ruby code shows that text_field() is called everytime when rendering, +but pp_text_field() is called only once when template is loaded. +This means that pp_text_field() with preprocessing makes view layer very fast. +

    +

    Module Erubis::Helpers::RailsFormHelper defines the following form helper methods. +

    +
      +
    • pp_render_partial(basename) +
    • +
    • pp_form_tag(url_for_options={}, options={}, *parameters_for_url, &block) +
    • +
    • pp_text_field(object_name, method, options={}) +
    • +
    • pp_password_field(object_name, method, options={}) +
    • +
    • pp_hidden_field(object_name, method, options={}) +
    • +
    • pp_file_field(object_name, method, options={}) +
    • +
    • pp_text_area(object_name, method, options={}) +
    • +
    • pp_check_box(object_name, method, options={}, checked_value="1", unchecked_value="0") +
    • +
    • pp_radio_button(object_name, method, tag_value, options={}) +
    • +
    • pp_select(object, method, collection, options={}, html_options={}) +
    • +
    • pp_collection_select(object, method, collection, value_method, text_method, options={}, html_options={}) +
    • +
    • pp_country_select(object, method, priority_countries=nil, options={}, html_options={}) +
    • +
    • pp_time_zone_select(object, method, priority_zones=nil, options={}, html_options={}) +
    • +
    • pp_submit_tag(value="Save changes", options={}) +
    • +
    • pp_image_submit_tag(source, options={}) +
    • +
    +

    Notice that pp_form_for() is not provided. +

    +

    CAUTION: These are experimental and may not work in Ruby on Rails 2.0. +

    +
    + + + +

    Others

    +
      +
    • ActionView::Helpers::CaptureHelper#capture() and ActionView::Helpers::Texthelper#concat() are available. +
    • +
    +
      +
    • Form helper methods are not tested in Ruby on Rails 2.0. +
    • +
    +
      +
    • ERB::Util.h() is redefined if you require 'erubis/helpers/rails_helper.rb'. + Original definition of ERB::Util.h() is the following and it is slow + because it scans string four times. +
       def html_escape(s)
      +   s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
      + end
      + alias h html_escape
      +
      +

      New definition in 'erubis/helpers/rails_helper.rb' is faster than the above + because it scans string only once. +

      +
       ESCAPE_TABLE = { '&'=>'&amp;', '<'=>'&lt;', '>'=>'&gt;', '"'=>'&quot;', "'"=>'&#039;', }
      + def h(value)
      +   value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] }
      + end
      +
      +

      Notice that the new definition may be slow if string contains + many '< > & "' characters because block is call many time. + You should use ERB::Util.html_hscape() if string contains a lot of '< > & "' + characters. +

      +
    • +
    +
    + + +
    + + + +

    Other Topics

    + +

    Erubis::FastEruby Class

    +

    Erubis::FastEruby class generates more effective code than Erubis::Eruby. +

    + +
    +fasteruby-example.rb
    +
    require 'erubis'
    +input = File.read('example.eruby')
    +
    +puts "----- Erubis::Eruby -----"
    +print Erubis::Eruby.new(input).src
    +
    +puts "----- Erubis::FastEruby -----"
    +print Erubis::FastEruby.new(input).src
    +
    + +
    +result
    +
    $ ruby fasteruby-example.rb
    +----- Erubis::Eruby -----
    +_buf = ''; _buf << '<div>
    +'; for item in list 
    + _buf << '  <p>'; _buf << ( item ).to_s; _buf << '</p>
    +  <p>'; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</p>
    +'; end 
    + _buf << '</div>
    +';
    +_buf.to_s
    +----- Erubis::FastEruby -----
    +_buf = ''; _buf << %Q`<div>\n`
    + for item in list 
    + _buf << %Q`  <p>#{ item }</p>
    +  <p>#{Erubis::XmlHelper.escape_xml( item )}</p>\n`
    + end 
    + _buf << %Q`</div>\n`
    +_buf.to_s
    +
    +

    Technically, Erubis::FastEruby is just a subclass of Erubis::Eruby and includes InterpolationEnhancer. Erubis::FastEruby is faster than Erubis::Eruby but is not extensible compared to Erubis::Eruby. This is the reason why Erubis::FastEruby is not the default class of Erubis. +

    +
    + + + +

    :bufvar Option

    +

    Since 2.7.0, Erubis supports :bufvar option which allows you to change buffer variable name (default '_buf'). +

    + +
    +bufvar-example.rb
    +
    require 'erubis'
    +input = File.read('example.eruby')
    +
    +puts "----- default -----"
    +eruby = Erubis::FastEruby.new(input)
    +puts eruby.src
    +
    +puts "----- with :bufvar option -----"
    +eruby = Erubis::FastEruby.new(input, :bufvar=>'@_out_buf')
    +print eruby.src
    +
    + +
    +result
    +
    $ ruby bufvar-example.rb
    +----- default -----
    +_buf = ''; _buf << %Q`<div>\n`
    + for item in list 
    + _buf << %Q`  <p>#{ item }</p>
    +  <p>#{Erubis::XmlHelper.escape_xml( item )}</p>\n`
    + end 
    + _buf << %Q`</div>\n`
    +_buf.to_s
    +----- with :bufvar option -----
    +@_out_buf = ''; @_out_buf << %Q`<div>\n`
    + for item in list 
    + @_out_buf << %Q`  <p>#{ item }</p>
    +  <p>#{Erubis::XmlHelper.escape_xml( item )}</p>\n`
    + end 
    + @_out_buf << %Q`</div>\n`
    +@_out_buf.to_s
    +
    +
    + + + +

    '<%= =%>' and '<%= -%>'

    +

    Since 2.6.0, '<%= -%>' remove tail spaces and newline. +This is for compatibiliy with ERB when trim mode is '-'. +'<%= =%>' also removes tail spaces and newlines, and this is +Erubis-original enhancement (cooler than '<%= -%>', isn't it?). +

    + +
    +tailnewline.rhtml
    +
    <div>
    +<%= @var -%>          # or <%= @var =%>
    +</div>
    +
    +
    +result (version 2.5.0):
    +
    $ erubis -c '{var: "AAA\n"}' tailnewline.rhtml
    +<div>
    +AAA
    +
    +</div>
    +
    + +
    +result (version 2.6.0):
    +
    $ erubis -c '{var: "AAA\n"}' tailnewline.rhtml
    +<div>
    +AAA
    +</div>
    +
    +
    + + + +

    '<%% %>' and '<%%= %>'

    +

    Since 2.6.0, '<%% %>' and '<%%= %>' are converted into '<% %>' and '<%= %>' respectively. +This is for compatibility with ERB. +

    +
    +doublepercent.rhtml:
    +
    <ul>
    +<%% for item in @list %>
    +  <li><%%= item %></li>
    +<%% end %>
    +</ul>
    +
    +
    +result:
    +
    $ erubis doublepercent.rhtml
    +<ul>
    +<% for item in @list %>
    +  <li><%= item %></li>
    +<% end %>
    +</ul>
    +
    +
    + + + +

    evaluate(context) v.s. result(binding)

    +

    It is recommended to use 'Erubis::Eruby#evaluate(context)' instead of 'Erubis::Eruby#result(binding)' because Ruby's Binding object has some problems. +

    +
      +
    • It is not able to specify variables to use. + Using binding() method, all of local variables are passed to templates. +
    • +
    • Changing local variables in templates may affect to varialbes in main program. + If you assign '10' to local variable 'x' in templates, it may change variable 'x' in main program unintendedly. +
    • +
    +

    The following example shows that assignment of some values into variable 'x' in templates affect to local variable 'x' in main program unintendedly. +

    + +
    +template1.rhtml (intended to be passed 'items' from main program)
    +
    <% for x in items %>
    +item = <%= x %>
    +<% end %>
    +** debug: local variables=<%= local_variables().inspect() %>
    +
    + +
    +main_program1.rb (intended to pass 'items' to template)
    +
    require 'erubis'
    +eruby = Erubis::Eruby.new(File.read('template1.rhtml'))
    +items = ['foo', 'bar', 'baz']
    +x = 1
    +## local variable 'x' and 'eruby' are passed to template as well as 'items'!
    +print eruby.result(binding())    
    +## local variable 'x' is changed unintendedly because it is changed in template!
    +puts "** debug: x=#{x.inspect}"  #=> "baz"
    +
    + +
    +Result:
    +
    $ ruby main_program1.rb
    +item = foo
    +item = bar
    +item = baz
    +** debug: local variables=["eruby", "items", "x", "_buf"]
    +** debug: x="baz"
    +
    +

    This problem is caused because Ruby's Binding class is poor to use in template engine. +Binding class should support the following features. +

    +
    b = Binding.new     # create empty Binding object
    +b['x'] = 1          # set local variables using binding object
    +
    +

    But the above features are not implemented in Ruby. +

    +

    A pragmatic solution is to use 'Erubis::Eruby#evaluate(context)' instead of 'Erubis::Eruby#result(binding)'. +'evaluate(context)' uses Erubis::Context object and instance variables instead of Binding object and local variables. +

    + +
    +template2.rhtml (intended to be passed '@items' from main program)
    +
    <% for x in @items %>
    +item = <%= x %>
    +<% end %>
    +** debug: local variables=<%= local_variables().inspect() %>
    +
    + +
    +main_program2.rb (intended to pass '@items' to template)
    +
    require 'erubis'
    +eruby = Erubis::Eruby.new(File.read('template2.rhtml'))
    +items = ['foo', 'bar', 'baz']
    +x = 1
    +## only 'items' are passed to template
    +print eruby.evaluate(:items=>items)    
    +## local variable 'x' is not changed!
    +puts "** debug: x=#{x.inspect}"  #=> 1
    +
    + +
    +Result:
    +
    $ ruby main_program2.rb
    +item = foo
    +item = bar
    +item = baz
    +** debug: local variables=["_context", "x", "_buf"]
    +** debug: x=1
    +
    +
    + + + +

    Class Erubis::FastEruby

    +

    [experimental] +

    +

    Erubis provides Erubis::FastEruby class which includes InterpolationEnhancer and works faster than Erubis::Eruby class. +If you desire more speed, try Erubis::FastEruby class. +

    + +
    +File 'fasteruby.rhtml':
    +
    <html>
    +  <body>
    +    <h1><%== @title %></h1>
    +    <table>
    +<% i = 0 %>
    +<% for item in @list %>
    +<%   i += 1 %>
    +      <tr>
    +        <td><%= i %></td>
    +        <td><%== item %></td>
    +      </tr>
    +<% end %>
    +    </table>
    +  </body>
    +</html>
    +
    + +
    +File 'fasteruby.rb':
    +
    require 'erubis'
    +input = File.read('fasteruby.rhtml')
    +eruby = Erubis::FastEruby.new(input)    # create Eruby object
    +
    +puts "---------- script source ---"
    +puts eruby.src
    +
    +puts "---------- result ----------"
    +context = { :title=>'Example', :list=>['aaa', 'bbb', 'ccc'] }
    +output = eruby.evaluate(context)
    +print output
    +
    + +
    +output
    +
    $ ruby fasteruby.rb
    +---------- script source ---
    +_buf = ''; _buf << %Q`<html>
    +  <body>
    +    <h1>#{Erubis::XmlHelper.escape_xml( @title )}</h1>
    +    <table>\n`
    + i = 0 
    + for item in @list 
    +   i += 1 
    + _buf << %Q`      <tr>
    +        <td>#{ i }</td>
    +        <td>#{Erubis::XmlHelper.escape_xml( item )}</td>
    +      </tr>\n`
    + end 
    + _buf << %Q`    </table>
    +  </body>
    +</html>\n`
    +_buf.to_s
    +---------- result ----------
    +<html>
    +  <body>
    +    <h1>Example</h1>
    +    <table>
    +      <tr>
    +        <td>1</td>
    +        <td>aaa</td>
    +      </tr>
    +      <tr>
    +        <td>2</td>
    +        <td>bbb</td>
    +      </tr>
    +      <tr>
    +        <td>3</td>
    +        <td>ccc</td>
    +      </tr>
    +    </table>
    +  </body>
    +</html>
    +
    +
    + + + +

    Syntax Checking

    +

    Command-line option '-z' checks syntax. It is similar to 'erubis -x file.rhtml | ruby -wc', but it can take several file names. +

    +
    +example of command-line option '-z'
    +
    $ erubis -z app/views/*/*.rhtml
    +Syntax OK
    +
    +
    + + + +

    File Caching

    +

    Erubis::Eruby.load_file(filename) convert file into Ruby script and return Eruby object. +In addition, it caches converted Ruby script into cache file (filename + '.cache') if cache file is old or not exist. +If cache file exists and is newer than eruby file, Erubis::Eruby.load_file() loads cache file. +

    +
    +example of Erubis::Eruby.load_file()
    +
    require 'erubis'
    +filename = 'example.rhtml'
    +eruby = Erubis::Eruby.load_file(filename)
    +cachename = filename + '.cache'
    +if test(?f, cachename)
    +  puts "*** cache file '#{cachename}' created."
    +end
    +
    +

    Since 2.6.0, it is able to specify cache filename. +

    +
    +specify cache filename.
    +
    filename = 'example.rhtml'
    +eruby = Erubis::Eruby.load_file(filename, :cachename=>filename+'.cache')
    +
    +

    Caching makes Erubis about 40-50 percent faster than no-caching. +See benchmark for details. +

    +
    + + + +

    Erubis::TinyEruby class

    +

    Erubis::TinyEruby class in 'erubis/tiny.rb' is the smallest implementation of eRuby. +If you don't need any enhancements of Erubis and only require simple eRuby implementation, +try Erubis::TinyEruby class. +

    +
    + + + +

    NoTextEnhancer and NoCodeEnhancer in PHP

    +

    NoTextEnhancer and NoCodEnahncer are quite useful not only for eRuby but also for PHP. +The former "drops" HTML text and show up embedded Ruby/PHP code +and the latter drops embedded Ruby/PHP code and leave HTML text. +

    +

    For example, see the following PHP script. +

    + +
    +notext-example.php
    +
    <html>
    +  <body>
    +    <h3>List</h3>
    +    <?php if (!$list || count($list) == 0) { ?>
    +    <p>not found.</p>
    +    <?php } else { ?>
    +    <table>
    +      <tbody>
    +        <?php $i = 0; ?>
    +        <?php foreach ($list as $item) { ?>
    +        <tr bgcolor="<?php echo ++$i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'; ?>">
    +          <td><?php echo $item; ?></td>
    +        </tr>
    +        <?php } ?>
    +      </tbody>
    +    </table>
    +    <?php } ?>
    +  </body>
    +</html>
    +
    +

    This is complex because PHP code and HTML document are mixed. +NoTextEnhancer can separate PHP code from HTML document. +

    + +
    +example of using NoTextEnhancer with PHP file
    +
    $ erubis -l php --pi=php -N -E NoText --trim=false notext-example.php
    +    1:  
    +    2:  
    +    3:  
    +    4:      <?php if (!$list || count($list) == 0) { ?>
    +    5:  
    +    6:      <?php } else { ?>
    +    7:  
    +    8:  
    +    9:          <?php $i = 0; ?>
    +   10:          <?php foreach ($list as $item) { ?>
    +   11:                       <?php echo ++$i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'; ?>
    +   12:                <?php echo $item; ?>
    +   13:  
    +   14:          <?php } ?>
    +   15:  
    +   16:  
    +   17:      <?php } ?>
    +   18:  
    +   19:  
    +
    +

    In the same way, NoCodeEnhancer can extract HTML tags. +

    + +
    +example of using NoCodeEnhancer with PHP file
    +
    $ erubis -l php --pi=php -N -E NoCode --trim=false notext-example.php
    +    1:  <html>
    +    2:    <body>
    +    3:      <h3>List</h3>
    +    4:      
    +    5:      <p>not found.</p>
    +    6:      
    +    7:      <table>
    +    8:        <tbody>
    +    9:          
    +   10:          
    +   11:          <tr bgcolor="">
    +   12:            <td></td>
    +   13:          </tr>
    +   14:          
    +   15:        </tbody>
    +   16:      </table>
    +   17:      
    +   18:    </body>
    +   19:  </html>
    +
    +
    + + + +

    Helper Class for mod_ruby

    +

    Thanks Andrew R Jackson, he developed 'erubis-run.rb' which enables you to use Erubis with mod_ruby. +

    +
      +
    1. Copy 'erubis-2.7.0/contrib/erubis-run.rb' to the 'RUBYLIBDIR/apache' directory (for example '/usr/local/lib/ruby/1.8/apache') which contains 'ruby-run.rb', 'eruby-run.rb', and so on. +
      $ cd erubis-2.7.0/
      +$ sudo copy contrib/erubis-run.rb /usr/local/lib/ruby/1.8/apache/
      +
      +
    2. +
    3. Add the following example to your 'httpd.conf' (for example '/usr/local/apache2/conf/httpd.conf') +
      LoadModule ruby_module modules/mod_ruby.so
      +<IfModule mod_ruby.c>
      +  RubyRequire apache/ruby-run
      +  RubyRequire apache/eruby-run
      +  RubyRequire apache/erubis-run
      +  <Location /erubis>
      +    SetHandler ruby-object
      +    RubyHandler Apache::ErubisRun.instance
      +  </Location>
      +  <Files *.rhtml>
      +    SetHandler ruby-object
      +    RubyHandler Apache::ErubisRun.instance
      +  </Files>
      +</IfModule>
      +
      +
    4. +
    5. Restart Apache web server. +
      $ sudo /usr/local/apache2/bin/apachectl stop
      +$ sudo /usr/local/apache2/bin/apachectl start
      +
      +
    6. +
    7. Create *.rhtml file, for example: +
      <html>
      + <body>
      +  Now is <%= Time.now %>
      +  Erubis version is <%= Erubis::VERSION %>
      + </body>
      +</html>
      +
      +
    8. +
    9. Change mode of your directory to be writable by web server process. +
      $ cd /usr/local/apache2/htdocs/erubis
      +$ sudo chgrp daemon .
      +$ sudo chmod 775 .
      +
      +
    10. +
    11. Access the *.rhtml file and you'll get the web page. +
    12. +
    +

    You must set your directories to be writable by web server process, because +Apache::ErubisRun calls Erubis::Eruby.load_file() internally which creates cache files +in the same directory in which '*.rhtml' file exists. +

    +
    + + + +

    Helper CGI Script for Apache

    +

    Erubis provides helper CGI script for Apache. +Using this script, it is very easy to publish *.rhtml files as *.html. +

    +
    ### install Erubis
    +$ tar xzf erubis-X.X.X.tar.gz
    +$ cd erubis-X.X.X/
    +$ ruby setup.py install
    +### copy files to ~/public_html
    +$ mkdir -p ~/public_html
    +$ cp public_html/_htaccess   ~/public_html/.htaccess
    +$ cp public_html/index.cgi   ~/public_html/
    +$ cp public_html/index.rhtml ~/public_html/
    +### add executable permission to index.cgi
    +$ chmod a+x ~/public_html/index.cgi
    +### edit .htaccess
    +$ vi ~/public_html/.htaccess
    +### (optional) edit index.cgi to configure
    +$ vi ~/public_html/index.cgi
    +
    +

    Edit ~/public_html/.htaccess and modify user name. +

    +
    +~/public_html/.htaccess
    +
    ## enable mod_rewrie
    +RewriteEngine on
    +## deny access to *.rhtml and *.cache
    +#RewriteRule \.(rhtml|cache)$ - [R=404,L]
    +RewriteRule \.(rhtml|cache)$ - [F,L]
    +## rewrite only if requested file is not found
    +RewriteCond %{SCRIPT_FILENAME} !-f
    +## handle request to *.html and directories by index.cgi
    +RewriteRule (\.html|/|^)$ /~username/index.cgi
    +#RewriteRule (\.html|/|^)$ index.cgi
    +
    +

    After these steps, *.rhtml will be published as *.html. +For example, if you access to http://host.domain/~username/index.html (or http://host.domain/~username/), file ~/public_html/index.rhtml will be displayed. +

    +
    + + + +

    Define method

    +

    Erubis::Eruby#def_method() defines instance method or singleton method. +

    + +
    require 'erubis'
    +s = "hello <%= name %>"
    +eruby = Erubis::Eruby.new(s)
    +filename = 'hello.rhtml'
    +
    +## define instance method to Dummy class (or module)
    +class Dummy; end
    +eruby.def_method(Dummy, 'render(name)', filename)  # filename is optional
    +p Dummy.new.render('world')    #=> "hello world"
    +
    +## define singleton method to dummy object
    +obj = Object.new
    +eruby.def_method(obj, 'render(name)', filename)    # filename is optional
    +p obj.render('world')          #=> "hello world"
    +
    +
    + + + +

    Benchmark

    +

    A benchmark script is included in Erubis package at 'erubis-2.7.0/benchark/' directory. +Here is an example result of benchmark. +

    +
    +MacOS X 10.4 Tiger, Intel CoreDuo 1.83GHz, Ruby1.8.6, eruby1.0.5, gcc4.0.1
    +
    $ cd erubis-2.7.0/benchmark/
    +$ ruby bench.rb -n 10000 -m execute
    +*** ntimes=10000, testmode=execute
    +                                    user     system      total        real
    +eruby                          12.720000   0.240000  12.960000 ( 12.971888)
    +ERB                            36.760000   0.350000  37.110000 ( 37.112019)
    +ERB(cached)                    11.990000   0.440000  12.430000 ( 12.430375)
    +Erubis::Eruby                  10.840000   0.300000  11.140000 ( 11.144426)
    +Erubis::Eruby(cached)           7.540000   0.410000   7.950000 (  7.969305)
    +Erubis::FastEruby              10.440000   0.300000  10.740000 ( 10.737808)
    +Erubis::FastEruby(cached)       6.940000   0.410000   7.350000 (  7.353666)
    +Erubis::TinyEruby               9.550000   0.290000   9.840000 (  9.851729)
    +Erubis::ArrayBufferEruby       11.010000   0.300000  11.310000 ( 11.314339)
    +Erubis::PrintOutEruby          11.640000   0.290000  11.930000 ( 11.942141)
    +Erubis::StdoutEruby            11.590000   0.300000  11.890000 ( 11.886512)
    +
    +

    This shows that... +

    +
      +
    • Erubis::Eruby runs more than 10 percent faster than eruby. +
    • +
    • Erubis::Eruby runs about 3 times faster than ERB. +
    • +
    • Caching (by Erubis::Eruby.load_file()) makes Erubis about 40-50 percent faster. +
    • +
    • Erubis::FastEruby is a litte faster than Erubis::Eruby. +
    • +
    • Array buffer (ArrayBufferEnhancer) is a little slower than string buffer (StringBufferEnhancer which Erubis::Eruby includes) +
    • +
    • $stdout and print() make Erubis a little slower. +
    • +
    • Erubis::TinyEruby (at 'erubis/tiny.rb') is the fastest in all eRuby implementations when no caching. +
    • +
    +

    Escaping HTML characters (such as '< > & "') makes Erubis more faster than eruby and ERB, +because Erubis::XmlHelper#escape_xml() works faster than CGI.escapeHTML() and ERB::Util#h(). +The following shows that Erubis runs more than 40 percent (when no-cached) or 90 percent (when cached) faster than eruby if HTML characters are escaped. +

    +
    +When escaping HTML characters with option '-e'
    +
    $ ruby bench.rb -n 10000 -m execute -ep
    +*** ntimes=10000, testmode=execute
    +                                    user     system      total        real
    +eruby                          21.700000   0.290000  21.990000 ( 22.050687)
    +ERB                            45.140000   0.390000  45.530000 ( 45.536976)
    +ERB(cached)                    20.340000   0.470000  20.810000 ( 20.822653)
    +Erubis::Eruby                  14.830000   0.310000  15.140000 ( 15.147930)
    +Erubis::Eruby(cached)          11.090000   0.420000  11.510000 ( 11.514954)
    +Erubis::FastEruby              14.850000   0.310000  15.160000 ( 15.172499)
    +Erubis::FastEruby(cached)      10.970000   0.430000  11.400000 ( 11.399605)
    +Erubis::ArrayBufferEruby       14.970000   0.300000  15.270000 ( 15.281061)
    +Erubis::PrintOutEruby          15.780000   0.300000  16.080000 ( 16.088289)
    +Erubis::StdoutEruby            15.840000   0.310000  16.150000 ( 16.235338)
    +
    +
    + + +
    + + + +

    Command Reference

    + +

    Usage

    +

    erubis [..options..] [file ...] +

    +
    + + + +

    Options

    +
    +
    +-h, --help
    +
    + Help. +
    +
    +-v
    +
    + Release version. +
    +
    +-x
    +
    + Show compiled source. +
    +
    +-X
    +
    + Show compiled source but only Ruby code. + This is equivarent to '-E NoText'. +
    +
    +-N
    +
    + Numbering: add line numbers. (for '-x/-X') +
    +
    +-U
    +
    + Unique mode: zip empty lines into a line. (for '-x/-X') +
    +
    +-C
    +
    + Compact: remove empty lines. (for '-x/-X') +
    +
    +-b
    +
    + Body only: no preamble nor postamble. (for '-x/-X') + This is equivarent to '--preamble=false --postamble=false'. +
    +
    +-z
    +
    + Syntax checking. +
    +
    +-e
    +
    + Escape. This is equivarent to '-E Escape'. +
    +
    +-p pattern
    +
    + Embedded pattern (default '<% %>'). + This is equivarent to '--pattern=pattern'. +
    +
    +-l lang
    +
    + Language name. + This option makes erubis command to compile script but no execute. +
    +
    +-E enhacers
    +
    + Enhancer name (Escape, PercentLine, ...). + It is able to specify several enhancer name separating with ',' + (ex. -f Escape,PercentLine,HeaderFooter). +
    +
    +-I path
    +
    + Require library path ($:). + It is able to specify several paths separating with ',' + (ex. -f path1,path2,path3). +
    +
    +-K kanji
    +
    + Kanji code (euc, sjis, utf8, or none) (default none). +
    +
    +-f datafile
    +
    + Context data file in YAML format ('*.yaml', '*.yml') or + Ruby script ('*.rb'). + It is able to specify several filenames separating with ',' + (ex. -f file1,file2,file3). +
    +
    +-c context
    +
    + Context data string in YAML inline style or Ruby code. +
    +
    +-T
    +
    + Don't expand tab characters in YAML file. +
    +
    +-S
    +
    + Convert mapping key from string to symbol in YAML file. +
    +
    +-B
    +
    + invoke Eruby#result() instead of Eruby#evaluate() +
    +
    +--pi[=name]
    +
    + parse '<?name ... ?>' instead of '<% ... %>' +
    +
    +--trim=false
    +
    + No trimming spaces around '<% %>'. +
    +
    +
    + + + +

    Properties

    +

    Some Eruby classes can take optional properties to change it's compile option. +For example, property '--indent=" "' may change indentation of compiled source code. +Try 'erubis -h' for details. +

    +
    + + +
    + + + +
    +
    + + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/Makefile b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/Makefile new file mode 100644 index 0000000..0550ceb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/Makefile @@ -0,0 +1,58 @@ +all = example.rb example.php example.c example.cpp example.java example.scm example.pl example.js + +all: $(all) + +example.rb: example.eruby + erubis -l ruby example.eruby > example.rb + + +example.php: example.ephp + erubis -l php example.ephp > example.php + +example.c: example.ec + erubis -bl c example.ec > example.c + +example.cpp: example.ecpp + erubis -bl cpp example.ecpp > example.cpp + +example.java: example.ejava + erubis -bl java example.ejava > example.java + +example.scm: example.escheme + erubis -l scheme --func=display example.escheme > example.scm +# erubis -l scheme example.escheme > example.scm + +example.pl: example.eperl + erubis -l perl example.eperl > example.pl + +example.js: example.ejs + erubis -l javascript example.ejs > example.js + + +###---------- + +src = example.eruby example.ephp example.ec example.ecpp example.ejava example.escheme example.eperl example.ejs Makefile + +clean: + rm -f `ruby -e 'puts(Dir.glob("*.*") - %w[$(src)])'` +# rm -f $(all) + +compile: example.bin example.class + +example.bin: example.c + cc -o example.bin example.c + g++ -o example.bin2 example.cpp + +example.class: example.java + jikes example.java + +output: $(all) example.bin example.class + erubis example.eruby > example.ruby.out + php example.php > example.php.out + ./example.bin '' 'b&b' '"ccc"' > example.c.out + ./example.bin2 '' 'b&b' '"ccc"' > example.cpp.out + java example > example.javexample.bin + gosh example.scm > example.scm.out +# guile example.scm > example.scm.out + perl example.pl > example.pl.out + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ec b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ec new file mode 100644 index 0000000..589bdb0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ec @@ -0,0 +1,42 @@ +<% +#include + +void escape(char *str, FILE *out); + +int main(int argc, char *argv[]) +{ + int i; + +%> +

    Hello <%== argv[0] %>!

    + + + <% for (i = 1; i < argc; i++) { %> + "> + + + + <% } %> + +
    <%= "%d", i %><%== argv[i] %>
    +<% + + return 0; +} + +void escape(char *str, FILE *out) +{ + char *pch; + for (pch = str; *pch != '\0'; pch++) { + switch (*pch) { + case '&': fputs("&", out); break; + case '>': fputs(">", out); break; + case '<': fputs("<", out); break; + case '"': fputs(""", out); break; + case '\'': fputs("'", out); break; + default: fputc(*pch, out); + } + } +} + +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ecpp b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ecpp new file mode 100644 index 0000000..44978b5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ecpp @@ -0,0 +1,33 @@ +<% +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int i; + std::stringstream _buf; + +%> + + +

    Hello <%= argv[0] %>!

    + + + <% for (i = 1; i < argc; i++) { %> + "> + + + + <% } %> + +
    <%= i %><%= argv[i] %>
    + + +<% + + std::string _output = _buf.str(); + std::cout << _output; + return 0; +} +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ejava b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ejava new file mode 100644 index 0000000..217295d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ejava @@ -0,0 +1,45 @@ +<% +import java.util.*; + +public class example { + + public static void main(String[] args) { + String user = "Erubis"; + String[] list = { "", "b&b", "\"ccc\"" }; + StringBuffer _buf = new StringBuffer(); +%> +

    Hello <%== user %>!

    + + + <% for (int i = 0; i < list.length; i++) { %> + "> + + + + <% } %> + +
    <%= i + 1 %><%== list[i] %>
    +<% + System.out.print(_buf.toString()); + } + + public static String escape(String s) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '<': sb.append("<"); break; + case '>': sb.append(">"); break; + case '&': sb.append("&"); break; + case '"': sb.append("""); break; + default: sb.append(ch); + } + } + return sb.toString(); + } + + public static String escape(int i) { + return Integer.toString(i); + } +} +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ejs b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ejs new file mode 100644 index 0000000..67b7b0c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ejs @@ -0,0 +1,16 @@ +<% + var user = 'Erubis'; + var list = ['', 'b&b', '"ccc"']; + %> +

    Hello <%= user %>!

    + + + <% var i; %> + <% for (i = 0; i < list.length; i++) { %> + + + + + <% } %> + +
    <%= i + 1 %><%= list[i] %>
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.eperl b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.eperl new file mode 100644 index 0000000..f1261dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.eperl @@ -0,0 +1,16 @@ +<% + my $user = 'Erubis'; + my @list = ('', 'b&b', '"ccc"'); +%> +

    Hello <%== $user %>!

    + + + <% $i = 0; %> + <% for $item (@list) { %> + "> + + + + <% } %> + +
    <%= $i %><%== $item %>
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ephp b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ephp new file mode 100644 index 0000000..b45d62d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.ephp @@ -0,0 +1,17 @@ +<% + $user = "World"; + $list = array('', 'b&b', '"ccc"'); +%> +

    Hello <%= $user %>!

    + + + <% $i = 0 %> + <% foreach ($list as $item) { %> + <% $i++; %> + + + + + <% } %> + +
    <%= $i %><%== $item %>
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.eruby new file mode 100644 index 0000000..ee1ed13 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.eruby @@ -0,0 +1,15 @@ +<% + user = 'Erubis' + list = ['', 'b&b', '"ccc"'] + %> +

    Hello <%= user %>!

    + + + <% list.each_with_index do |item, i| %> + + + + + <% end %> + +
    <%= i + 1 %><%== item %>
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.escheme b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.escheme new file mode 100644 index 0000000..419ef77 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/basic/example.escheme @@ -0,0 +1,26 @@ +<% +(let ((user "Erubis") + (items '("" "b&b" "\"ccc\"")) + (i 0)) + %> +

    Hello <%= user %>!

    + + +<% + (for-each + (lambda (item) + (set! i (+ i 1)) + %> + "> + + + +<% + ) ; lambda end + items) ; for-each end + %> + +
    <%= i %><%= item %>
    +<% +) ; let end +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/Makefile b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/Makefile new file mode 100644 index 0000000..de12772 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/Makefile @@ -0,0 +1,54 @@ +all = example.rb example.php example.c example.java example.scm example.pl example.js + +all: $(all) + +example.rb: example.eruby + erubis --pi -l ruby example.eruby > example.rb + + +example.php: example.ephp + erubis --pi -l php example.ephp > example.php + +example.c: example.ec + erubis --pi -bl c example.ec > example.c + +example.java: example.ejava + erubis --pi -bl java example.ejava > example.java + +example.scm: example.escheme + erubis --pi -l scheme --func=display example.escheme > example.scm +# erubis --pi -l scheme example.escheme > example.scm + +example.pl: example.eperl + erubis --pi -l perl example.eperl > example.pl + +example.js: example.ejs + erubis --pi -l javascript example.ejs > example.js + + +###---------- + +src = example.eruby example.ephp example.ec example.ejava example.escheme example.eperl example.ejs Makefile + +clean: + rm -f `ruby -e 'puts(Dir.glob("*.*") - %w[$(src)])'` +# rm -f $(all) + +compile: example.bin example.class + +example.bin: example.c + cc -o example.bin example.c + +example.class: example.java + jikes example.java + +output: $(all) example.bin example.class + erubis --pi example.eruby > example.ruby.result + #ruby example.rb > example.ruby.result + php example.php > example.php.result + ./example.bin '' 'b&b' '"ccc"' > example.c.result + java example > example.java.result + gosh example.scm > example.scm.result + #guile example.scm > example.scm.result + perl example.pl > example.pl.result + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ec b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ec new file mode 100644 index 0000000..ddec571 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ec @@ -0,0 +1,42 @@ + + +void escape(char *str, FILE *out); + +int main(int argc, char *argv[]) +{ + int i; + +?> +

    Hello @!{argv[0]}@!

    + + + + + + + + + +
    @!{"%d", i}@@{argv[i]}@
    +': fputs(">", out); break; + case '<': fputs("<", out); break; + case '"': fputs(""", out); break; + case '\'': fputs("'", out); break; + default: fputc(*pch, out); + } + } +} + +?> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ejava b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ejava new file mode 100644 index 0000000..beca150 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ejava @@ -0,0 +1,45 @@ +", "b&b", "\"ccc\"" }; + StringBuffer _buf = new StringBuffer(); +?> +

    Hello @{user}@!

    + + + + + + + + + +
    @!{i + 1}@@{list[i]}@
    +': sb.append(">"); break; + case '&': sb.append("&"); break; + case '"': sb.append("""); break; + default: sb.append(ch); + } + } + return sb.toString(); + } + + public static String escape(int i) { + return Integer.toString(i); + } +} +?> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ejs b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ejs new file mode 100644 index 0000000..f12ae42 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ejs @@ -0,0 +1,16 @@ +', 'b&b', '"ccc"']; + ?> +

    Hello @{user}@!

    + + + + + + + + + + +
    @{i + 1}@@{list[i]}@
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.eperl b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.eperl new file mode 100644 index 0000000..c115ed4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.eperl @@ -0,0 +1,16 @@ +', 'b&b', '"ccc"'); +?> +

    Hello @{$user}@!

    + + + + + + + + + + +
    @!{$i}@@{$item}@
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ephp b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ephp new file mode 100644 index 0000000..dbdd884 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.ephp @@ -0,0 +1,17 @@ +', 'b&b', '"ccc"'); +?> +

    Hello @{$user}@!

    + + + + + + + + + + + +
    @!{$i}@@{$item}@
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.eruby new file mode 100644 index 0000000..85218d1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.eruby @@ -0,0 +1,15 @@ +', 'b&b', '"ccc"'] + ?> +

    Hello @{user}@!

    + + + + + + + + + +
    @!{i + 1}@@{item}@
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.escheme b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.escheme new file mode 100644 index 0000000..08b1cf5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/examples/pi/example.escheme @@ -0,0 +1,26 @@ +" "b&b" "\"ccc\"")) + (i 0)) + ?> +

    Hello @!{user}@!

    + + + + + + + + + +
    @!{i}@@!{item}@
    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis.rb new file mode 100644 index 0000000..88aed35 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis.rb @@ -0,0 +1,73 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +## +## an implementation of eRuby +## +## ex. +## input = <<'END' +##
      +## <% for item in @list %> +##
    • <%= item %> +## <%== item %>
    • +## <% end %> +##
    +## END +## list = ['', 'b&b', '"ccc"'] +## eruby = Erubis::Eruby.new(input) +## puts "--- code ---" +## puts eruby.src +## puts "--- result ---" +## context = Erubis::Context.new() # or new(:list=>list) +## context[:list] = list +## puts eruby.evaluate(context) +## +## result: +## --- source --- +## _buf = ''; _buf << '
      +## '; for item in @list +## _buf << '
    • '; _buf << ( item ).to_s; _buf << ' +## '; _buf << ' '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
    • +## '; end +## _buf << '
    +## '; +## _buf.to_s +## --- result --- +##
      +##
    • +## <aaa>
    • +##
    • b&b +## b&b
    • +##
    • "ccc" +## "ccc"
    • +##
    +## + + +module Erubis + VERSION = ('$Release: 2.7.0 $' =~ /([.\d]+)/) && $1 +end + +require 'erubis/engine' +#require 'erubis/generator' +#require 'erubis/converter' +#require 'erubis/evaluator' +#require 'erubis/error' +#require 'erubis/context' +#requier 'erubis/util' +require 'erubis/helper' +require 'erubis/enhancer' +#require 'erubis/tiny' +require 'erubis/engine/eruby' +#require 'erubis/engine/enhanced' # enhanced eruby engines +#require 'erubis/engine/optimized' # generates optimized ruby code +#require 'erubis/engine/ephp' +#require 'erubis/engine/ec' +#require 'erubis/engine/ejava' +#require 'erubis/engine/escheme' +#require 'erubis/engine/eperl' +#require 'erubis/engine/ejavascript' + +require 'erubis/local-setting' diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/context.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/context.rb new file mode 100644 index 0000000..a70d297 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/context.rb @@ -0,0 +1,83 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +module Erubis + + + ## + ## context object for Engine#evaluate + ## + ## ex. + ## template = <<'END' + ## Hello <%= @user %>! + ## <% for item in @list %> + ## - <%= item %> + ## <% end %> + ## END + ## + ## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c']) + ## # or + ## # context = Erubis::Context.new + ## # context[:user] = 'World' + ## # context[:list] = ['a', 'b', 'c'] + ## + ## eruby = Erubis::Eruby.new(template) + ## print eruby.evaluate(context) + ## + class Context + include Enumerable + + def initialize(hash=nil) + hash.each do |name, value| + self[name] = value + end if hash + end + + def [](key) + return instance_variable_get("@#{key}") + end + + def []=(key, value) + return instance_variable_set("@#{key}", value) + end + + def keys + return instance_variables.collect { |name| name[1..-1] } + end + + def each + instance_variables.each do |name| + key = name[1..-1] + value = instance_variable_get(name) + yield(key, value) + end + end + + def to_hash + hash = {} + self.keys.each { |key| hash[key] = self[key] } + return hash + end + + def update(context_or_hash) + arg = context_or_hash + if arg.is_a?(Hash) + arg.each do |key, val| + self[key] = val + end + else + arg.instance_variables.each do |varname| + key = varname[1..-1] + val = arg.instance_variable_get(varname) + self[key] = val + end + end + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/converter.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/converter.rb new file mode 100644 index 0000000..a28a7ad --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/converter.rb @@ -0,0 +1,357 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/util' + +module Erubis + + + ## + ## convert + ## + module Converter + + attr_accessor :preamble, :postamble, :escape + + def self.supported_properties # :nodoc: + return [ + [:preamble, nil, "preamble (no preamble when false)"], + [:postamble, nil, "postamble (no postamble when false)"], + [:escape, nil, "escape expression or not in default"], + ] + end + + def init_converter(properties={}) + @preamble = properties[:preamble] + @postamble = properties[:postamble] + @escape = properties[:escape] + end + + ## convert input string into target language + def convert(input) + codebuf = "" # or [] + @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble)) + convert_input(codebuf, input) + @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble)) + @_proc = nil # clear cached proc object + return codebuf # or codebuf.join() + end + + protected + + ## + ## detect spaces at beginning of line + ## + def detect_spaces_at_bol(text, is_bol) + lspace = nil + if text.empty? + lspace = "" if is_bol + elsif text[-1] == ?\n + lspace = "" + else + rindex = text.rindex(?\n) + if rindex + s = text[rindex+1..-1] + if s =~ /\A[ \t]*\z/ + lspace = s + #text = text[0..rindex] + text[rindex+1..-1] = '' + end + else + if is_bol && text =~ /\A[ \t]*\z/ + #lspace = text + #text = nil + lspace = text.dup + text[0..-1] = '' + end + end + end + return lspace + end + + ## + ## (abstract) convert input to code + ## + def convert_input(codebuf, input) + not_implemented + end + + end + + + module Basic + end + + + ## + ## basic converter which supports '<% ... %>' notation. + ## + module Basic::Converter + include Erubis::Converter + + def self.supported_properties # :nodoc: + return [ + [:pattern, '<% %>', "embed pattern"], + [:trim, true, "trim spaces around <% ... %>"], + ] + end + + attr_accessor :pattern, :trim + + def init_converter(properties={}) + super(properties) + @pattern = properties[:pattern] + @trim = properties[:trim] != false + end + + protected + + ## return regexp of pattern to parse eRuby script + def pattern_regexp(pattern) + @prefix, @postfix = pattern.split() # '<% %>' => '<%', '%>' + #return /(.*?)(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m + #return /(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m + return /#{@prefix}(=+|-|\#|%)?(.*?)([-=])?#{@postfix}([ \t]*\r?\n)?/m + end + module_function :pattern_regexp + + #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + #DEFAULT_REGEXP = /<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + DEFAULT_REGEXP = pattern_regexp('<% %>') + + public + + def convert_input(src, input) + pat = @pattern + regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat) + pos = 0 + is_bol = true # is beginning of line + input.scan(regexp) do |indicator, code, tailch, rspace| + match = Regexp.last_match() + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + ch = indicator ? indicator[0] : nil + lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol) + is_bol = rspace ? true : false + add_text(src, text) if text && !text.empty? + ## * when '<%= %>', do nothing + ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>' + if ch == ?= # <%= %> + rspace = nil if tailch && !tailch.empty? + add_text(src, lspace) if lspace + add_expr(src, code, indicator) + add_text(src, rspace) if rspace + elsif ch == ?\# # <%# %> + n = code.count("\n") + (rspace ? 1 : 0) + if @trim && lspace && rspace + add_stmt(src, "\n" * n) + else + add_text(src, lspace) if lspace + add_stmt(src, "\n" * n) + add_text(src, rspace) if rspace + end + elsif ch == ?% # <%% %> + s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}" + add_text(src, s) + else # <% %> + if @trim && lspace && rspace + add_stmt(src, "#{lspace}#{code}#{rspace}") + else + add_text(src, lspace) if lspace + add_stmt(src, code) + add_text(src, rspace) if rspace + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(src, rest) + end + + ## add expression code to src + def add_expr(src, code, indicator) + case indicator + when '=' + @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code) + when '==' + @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code) + when '===' + add_expr_debug(src, code) + end + end + + end + + + module PI + end + + ## + ## Processing Instructions (PI) converter for XML. + ## this class converts '' and '${...}' notation. + ## + module PI::Converter + include Erubis::Converter + + def self.desc # :nodoc: + "use processing instructions (PI) instead of '<% %>'" + end + + def self.supported_properties # :nodoc: + return [ + [:trim, true, "trim spaces around <% ... %>"], + [:pi, 'rb', "PI (Processing Instrunctions) name"], + [:embchar, '@', "char for embedded expression pattern('@{...}@')"], + [:pattern, '<% %>', "embed pattern"], + ] + end + + attr_accessor :pi, :prefix + + def init_converter(properties={}) + super(properties) + @trim = properties.fetch(:trim, true) + @pi = properties[:pi] if properties[:pi] + @embchar = properties[:embchar] || '@' + @pattern = properties[:pattern] + @pattern = '<% %>' if @pattern.nil? #|| @pattern == true + end + + def convert(input) + code = super(input) + return @header || @footer ? "#{@header}#{code}#{@footer}" : code + end + + protected + + def convert_input(codebuf, input) + unless @regexp + @pi ||= 'e' + ch = Regexp.escape(@embchar) + if @pattern + left, right = @pattern.split(' ') + @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m + else + @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m + end + end + # + is_bol = true + pos = 0 + input.scan(@regexp) do |pi_arg, stmt, rspace, + indicator1, expr1, indicator2, expr2| + match = Regexp.last_match + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil + is_bol = stmt && rspace ? true : false + add_text(codebuf, text) # unless text.empty? + # + if stmt + if @trim && lspace && rspace + add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg) + else + add_text(codebuf, lspace) if lspace + add_pi_stmt(codebuf, stmt, pi_arg) + add_text(codebuf, rspace) if rspace + end + else + add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2) + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(codebuf, rest) + end + + #-- + #def convert_input(codebuf, input) + # parse_stmts(codebuf, input) + # #parse_stmts2(codebuf, input) + #end + # + #def parse_stmts(codebuf, input) + # #regexp = pattern_regexp(@pattern) + # @pi ||= 'e' + # @stmt_pattern ||= /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m + # is_bol = true + # pos = 0 + # input.scan(@stmt_pattern) do |pi_arg, code, rspace| + # match = Regexp.last_match + # len = match.begin(0) - pos + # text = input[pos, len] + # pos = match.end(0) + # lspace = detect_spaces_at_bol(text, is_bol) + # is_bol = rspace ? true : false + # parse_exprs(codebuf, text) # unless text.empty? + # if @trim && lspace && rspace + # add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg) + # else + # add_text(codebuf, lspace) + # add_pi_stmt(codebuf, code, pi_arg) + # add_text(codebuf, rspace) + # end + # end + # rest = $' || input + # parse_exprs(codebuf, rest) + #end + # + #def parse_exprs(codebuf, input) + # unless @expr_pattern + # ch = Regexp.escape(@embchar) + # if @pattern + # left, right = @pattern.split(' ') + # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/ + # else + # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/ + # end + # end + # pos = 0 + # input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2| + # indicator = indicator1 || indicator2 + # code = code1 || code2 + # match = Regexp.last_match + # len = match.begin(0) - pos + # text = input[pos, len] + # pos = match.end(0) + # add_text(codebuf, text) # unless text.empty? + # add_pi_expr(codebuf, code, indicator) + # end + # rest = $' || input + # add_text(codebuf, rest) + #end + #++ + + def add_pi_stmt(codebuf, code, pi_arg) # :nodoc: + case pi_arg + when nil ; add_stmt(codebuf, code) + when 'header' ; @header = code + when 'footer' ; @footer = code + when 'comment'; add_stmt(codebuf, "\n" * code.count("\n")) + when 'value' ; add_expr_literal(codebuf, code) + else ; add_stmt(codebuf, code) + end + end + + def add_pi_expr(codebuf, code, indicator) # :nodoc: + case indicator + when nil, '', '==' # @{...}@ or <%== ... %> + @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code) + when '!', '=' # @!{...}@ or <%= ... %> + @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code) + when '!!', '===' # @!!{...}@ or <%=== ... %> + add_expr_debug(codebuf, code) + else + # ignore + end + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine.rb new file mode 100644 index 0000000..d020062 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine.rb @@ -0,0 +1,120 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +require 'erubis/generator' +require 'erubis/converter' +require 'erubis/evaluator' +require 'erubis/context' + + +module Erubis + + + ## + ## (abstract) abstract engine class. + ## subclass must include evaluator and converter module. + ## + class Engine + #include Evaluator + #include Converter + #include Generator + + def initialize(input=nil, properties={}) + #@input = input + init_generator(properties) + init_converter(properties) + init_evaluator(properties) + @src = convert(input) if input + end + + + ## + ## convert input string and set it to @src + ## + def convert!(input) + @src = convert(input) + end + + + ## + ## load file, write cache file, and return engine object. + ## this method create code cache file automatically. + ## cachefile name can be specified with properties[:cachename], + ## or filname + 'cache' is used as default. + ## + def self.load_file(filename, properties={}) + cachename = properties[:cachename] || (filename + '.cache') + properties[:filename] = filename + timestamp = File.mtime(filename) + if test(?f, cachename) && timestamp == File.mtime(cachename) + engine = self.new(nil, properties) + engine.src = File.read(cachename) + else + input = File.open(filename, 'rb') {|f| f.read } + engine = self.new(input, properties) + tmpname = cachename + rand().to_s[1,8] + File.open(tmpname, 'wb') {|f| f.write(engine.src) } + File.rename(tmpname, cachename) + File.utime(timestamp, timestamp, cachename) + end + engine.src.untaint # ok? + return engine + end + + + ## + ## helper method to convert and evaluate input text with context object. + ## context may be Binding, Hash, or Object. + ## + def process(input, context=nil, filename=nil) + code = convert(input) + filename ||= '(erubis)' + if context.is_a?(Binding) + return eval(code, context, filename) + else + context = Context.new(context) if context.is_a?(Hash) + return context.instance_eval(code, filename) + end + end + + + ## + ## helper method evaluate Proc object with contect object. + ## context may be Binding, Hash, or Object. + ## + def process_proc(proc_obj, context=nil, filename=nil) + if context.is_a?(Binding) + filename ||= '(erubis)' + return eval(proc_obj, context, filename) + else + context = Context.new(context) if context.is_a?(Hash) + return context.instance_eval(&proc_obj) + end + end + + + end # end of class Engine + + + ## + ## (abstract) base engine class for Eruby, Eperl, Ejava, and so on. + ## subclass must include generator. + ## + class Basic::Engine < Engine + include Evaluator + include Basic::Converter + include Generator + end + + + class PI::Engine < Engine + include Evaluator + include PI::Converter + include Generator + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ec.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ec.rb new file mode 100644 index 0000000..4ca3222 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ec.rb @@ -0,0 +1,117 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module CGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:indent, '', "indent spaces (ex. ' ')"], + [:out, 'stdout', "output file pointer name"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= "escape" + @indent = properties[:indent] || '' + @out = properties[:out] || 'stdout' + end + + def add_preamble(src) + src << "#line 1 \"#{self.filename}\"\n" if self.filename + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } + return text + end + + def escaped_expr(code) + return "#{@escapefunc}(#{code.strip}, #{@out})" + end + + def add_text(src, text) + return if text.empty? + src << (src.empty? || src[-1] == ?\n ? @indent : ' ') + src << "fputs(" + i = 0 + text.each_line do |line| + src << "\n" << @indent << ' ' if i > 0 + i += 1 + src << '"' << escape_text(line) << '"' + end + src << ", #{@out});" #<< (text[-1] == ?\n ? "\n" : "") + src << "\n" if text[-1] == ?\n + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << " fprintf(#{@out}, " << code.strip << ');' + end + + def add_expr_escaped(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << ' ' << escaped_expr(code) << ';' + end + + def add_expr_debug(src, code) + code.strip! + s = nil + if code =~ /\A\".*?\"\s*,\s*(.*)/ + s = $1.gsub(/[%"]/, '\\\1') + '=' + end + src << @indent if src.empty? || src[-1] == ?\n + src << " fprintf(stderr, \"*** debug: #{s}\" #{code});" + end + + def add_postamble(src) + # empty + end + + end + + + ## + ## engine for C + ## + class Ec < Basic::Engine + include CGenerator + end + + + class EscapedEc < Ec + include EscapeEnhancer + end + + + #class XmlEc < Ec + # include EscapeEnhancer + #end + + class PI::Ec < PI::Engine + include CGenerator + + def init_converter(properties={}) + @pi = 'c' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ecpp.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ecpp.rb new file mode 100644 index 0000000..5ce2c40 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ecpp.rb @@ -0,0 +1,113 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module CppGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:indent, '', "indent spaces (ex. ' ')"], + [:bufvar, '_buf', "buffer variable name"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= "escape" + @indent = properties[:indent] || '' + @bufvar = properties[:bufvar] || '_buf' + end + + def add_preamble(src) + src << "#line 1 \"#{self.filename}\"\n" if self.filename + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } + return text + end + + def escaped_expr(code) + return "#{@escapefunc}(#{code.strip})" + end + + def add_text(src, text) + return if text.empty? + src << (src.empty? || src[-1] == ?\n ? @indent : ' ') + src << "_buf << " + i = 0 + text.each_line do |line| + src << "\n" << @indent << " " if i > 0 + i += 1 + src << '"' << escape_text(line) << '"' + end + src << ";" #<< (text[-1] == ?\n ? "\n" : "") + src << "\n" if text[-1] == ?\n + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << " _buf << (" << code.strip << ");" + end + + def add_expr_escaped(src, code) + src << @indent if src.empty? || src[-1] == ?\n + src << ' ' << escaped_expr(code) << ';' + end + + def add_expr_debug(src, code) + code.strip! + src << @indent if src.empty? || src[-1] == ?\n + src << " std::cerr << \"*** debug: #{code.gsub(/(")/, '\\\&')}=\" << (#{code});" + end + + def add_postamble(src) + # empty + end + + end + + + ## + ## engine for C + ## + class Ecpp < Basic::Engine + include CppGenerator + end + + + class EscapedEcpp < Ecpp + include EscapeEnhancer + end + + + #class XmlEcpp < Ecpp + # include EscapeEnhancer + #end + + class PI::Ecpp < PI::Engine + include CppGenerator + + def init_converter(properties={}) + @pi = 'cpp' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ejava.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ejava.rb new file mode 100644 index 0000000..ba0790a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ejava.rb @@ -0,0 +1,110 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module JavaGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:indent, '', "indent spaces (ex. ' ')"], + [:bufvar, '_buf', "output buffer variable name"], + [:bufclass, 'StringBuffer', "output buffer class (ex. 'StringBuilder')"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'escape' + @indent = properties[:indent] || '' + @bufvar = properties[:bufvar] || '_buf' + @bufclass = properties[:bufclass] || 'StringBuffer' + end + + def add_preamble(src) + src << "#{@indent}#{@bufclass} #{@bufvar} = new #{@bufclass}();" + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text + end + + def add_text(src, text) + return if text.empty? + src << (src.empty? || src[-1] == ?\n ? @indent : ' ') + src << @bufvar << ".append(" + i = 0 + text.each_line do |line| + src << "\n" << @indent << ' + ' if i > 0 + i += 1 + src << '"' << escape_text(line) << '"' + end + src << ");" << (text[-1] == ?\n ? "\n" : "") + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + src << @indent if src.empty? || src[-1] == ?\n + code.strip! + src << " #{@bufvar}.append(#{code});" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + code.strip! + src << @indent if src.empty? || src[-1] == ?\n + src << " System.err.println(\"*** debug: #{code}=\"+(#{code}));" + end + + def add_postamble(src) + src << "\n" if src[-1] == ?; + src << @indent << "return " << @bufvar << ".toString();\n" + #src << @indent << "System.out.print(" << @bufvar << ".toString());\n" + end + + end + + + ## + ## engine for Java + ## + class Ejava < Basic::Engine + include JavaGenerator + end + + + class EscapedEjava < Ejava + include EscapeEnhancer + end + + + #class XmlEjava < Ejava + # include EscapeEnhancer + #end + + class PI::Ejava < PI::Engine + include JavaGenerator + + def init_converter(properties={}) + @pi = 'java' + super(properties) + end + + end + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ejavascript.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ejavascript.rb new file mode 100644 index 0000000..22a52f5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ejavascript.rb @@ -0,0 +1,119 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module JavascriptGenerator + include Generator + + def self.supported_properties() # :nodoc: + list = [] + #list << [:indent, '', "indent spaces (ex. ' ')"] + #list << [:bufvar, '_buf', "output buffer variable name"] + list << [:docwrite, true, "use 'document.write()' when true"] + return list + end + + def init_generator(properties={}) + super + @escapefunc ||= 'escape' + @indent = properties[:indent] || '' + @bufvar = properties[:bufvar] || '_buf' + @docwrite = properties[:docwrite] != false # '!= false' will be removed in the next release + end + + def add_preamble(src) + src << "#{@indent}var #{@bufvar} = [];" + end + + def escape_text(text) + @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n\\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" } + return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text + end + + def add_indent(src, indent) + src << (src.empty? || src[-1] == ?\n ? indent : ' ') + end + + def add_text(src, text) + return if text.empty? + add_indent(src, @indent) + src << @bufvar << '.push("' + s = escape_text(text) + if s[-1] == ?\n + s[-2, 2] = '' + src << s << "\");\n" + else + src << s << "\");" + end + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + add_indent(src, @indent) + code.strip! + src << "#{@bufvar}.push(#{code});" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + add_indent(src, @indent) + code.strip! + src << "alert(\"*** debug: #{code}=\"+(#{code}));" + end + + def add_postamble(src) + src << "\n" if src[-1] == ?; + if @docwrite + src << @indent << 'document.write(' << @bufvar << ".join(\"\"));\n" + else + src << @indent << @bufvar << ".join(\"\");\n" + end + end + + end + + + ## + ## engine for JavaScript + ## + class Ejavascript < Basic::Engine + include JavascriptGenerator + end + + + class EscapedEjavascript < Ejavascript + include EscapeEnhancer + end + + + #class XmlEjavascript < Ejavascript + # include EscapeEnhancer + #end + + + class PI::Ejavascript < PI::Engine + include JavascriptGenerator + + def init_converter(properties={}) + @pi = 'js' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/enhanced.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/enhanced.rb new file mode 100644 index 0000000..0121a5f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/enhanced.rb @@ -0,0 +1,126 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/enhancer' +require 'erubis/engine/eruby' + + +module Erubis + + + #-- + ## moved to engine/ruby.rb + #class EscapedEruby < Eruby + # include EscapeEnhancer + #end + #++ + + + #-- + ### (obsolete) + #class FastEruby < Eruby + # include FastEnhancer + #end + #++ + + + class StdoutEruby < Eruby + include StdoutEnhancer + end + + + class PrintOutEruby < Eruby + include PrintOutEnhancer + end + + + class PrintEnabledEruby < Eruby + include PrintEnabledEnhancer + end + + + class ArrayEruby < Eruby + include ArrayEnhancer + end + + + class ArrayBufferEruby < Eruby + include ArrayBufferEnhancer + end + + + class StringBufferEruby < Eruby + include StringBufferEnhancer + end + + + class StringIOEruby < Eruby + include StringIOEnhancer + end + + + class ErboutEruby < Eruby + include ErboutEnhancer + end + + + class NoTextEruby < Eruby + include NoTextEnhancer + end + + + class NoCodeEruby < Eruby + include NoCodeEnhancer + end + + + class SimplifiedEruby < Eruby + include SimplifyEnhancer + end + + + class StdoutSimplifiedEruby < Eruby + include StdoutEnhancer + include SimplifyEnhancer + end + + + class PrintOutSimplifiedEruby < Eruby + include PrintOutEnhancer + include SimplifyEnhancer + end + + + class BiPatternEruby < Eruby + include BiPatternEnhancer + end + + + class PercentLineEruby < Eruby + include PercentLineEnhancer + end + + + class PrefixedLineEruby < Eruby + include PrefixedLineEnhancer + end + + + class HeaderFooterEruby < Eruby + include HeaderFooterEnhancer + end + + + class DeleteIndentEruby < Eruby + include DeleteIndentEnhancer + end + + + class InterpolationEruby < Eruby + include InterpolationEnhancer + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/eperl.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/eperl.rb new file mode 100644 index 0000000..aa206fa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/eperl.rb @@ -0,0 +1,95 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module PerlGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:func, 'print', "function name"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'encode_entities' + @func = properties[:func] || 'print' + end + + def add_preamble(src) + src << "use HTML::Entities; "; + end + + def escape_text(text) + return text.gsub!(/['\\]/, '\\\\\&') || text + end + + def add_text(src, text) + src << @func << "('" << escape_text(text) << "'); " unless text.empty? + end + + def add_expr_literal(src, code) + code.strip! + src << @func << "(" << code << "); " + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + code.strip! + s = code.gsub(/\'/, "\\'") + src << @func << "('*** debug: #{code}=', #{code}, \"\\n\");" + end + + def add_stmt(src, code) + src << code + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + end + + end + + + ## + ## engine for Perl + ## + class Eperl < Basic::Engine + include PerlGenerator + end + + + class EscapedEperl < Eperl + include EscapeEnhancer + end + + + #class XmlEperl < Eperl + # include EscapeEnhancer + #end + + + class PI::Eperl < PI::Engine + include PerlGenerator + + def init_converter(properties={}) + @pi = 'perl' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ephp.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ephp.rb new file mode 100644 index 0000000..0684b3d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/ephp.rb @@ -0,0 +1,99 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module PhpGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'htmlspecialchars' + end + + def add_preamble(src) + # empty + end + + def escape_text(text) + return text.gsub!(/<\?xml\b/, '<?xml') || text + end + + def add_text(src, text) + src << escape_text(text) + end + + def add_expr_literal(src, code) + code.strip! + src << "" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + code.strip! + s = code.gsub(/\'/, "\\'") + src << "" + end + + def add_stmt(src, code) + src << "\n" + else + src << code << "?>" + end + end + + def add_postamble(src) + # empty + end + + end + + + ## + ## engine for PHP + ## + class Ephp < Basic::Engine + include PhpGenerator + end + + + class EscapedEphp < Ephp + include EscapeEnhancer + end + + + #class XmlEphp < Ephp + # include EscapeEnhancer + #end + + + class PI::Ephp < PI::Engine + include PhpGenerator + + def init_converter(properties={}) + @pi = 'php' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/eruby.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/eruby.rb new file mode 100644 index 0000000..02e3d4e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/eruby.rb @@ -0,0 +1,125 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + ## + ## code generator for Ruby + ## + module RubyGenerator + include Generator + #include ArrayBufferEnhancer + include StringBufferEnhancer + + def init_generator(properties={}) + super + @escapefunc ||= "Erubis::XmlHelper.escape_xml" + @bufvar = properties[:bufvar] || "_buf" + end + + def self.supported_properties() # :nodoc: + return [] + end + + def escape_text(text) + text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\' + end + + def escaped_expr(code) + return "#{@escapefunc}(#{code})" + end + + #-- + #def add_preamble(src) + # src << "#{@bufvar} = [];" + #end + #++ + + def add_text(src, text) + src << " #{@bufvar} << '" << escape_text(text) << "';" unless text.empty? + end + + def add_stmt(src, code) + #src << code << ';' + src << code + src << ';' unless code[-1] == ?\n + end + + def add_expr_literal(src, code) + src << " #{@bufvar} << (" << code << ').to_s;' + end + + def add_expr_escaped(src, code) + src << " #{@bufvar} << " << escaped_expr(code) << ';' + end + + def add_expr_debug(src, code) + code.strip! + s = (code.dump =~ /\A"(.*)"\z/) && $1 + src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");' + end + + #-- + #def add_postamble(src) + # src << "\n#{@bufvar}.join\n" + #end + #++ + + end + + + ## + ## engine for Ruby + ## + class Eruby < Basic::Engine + include RubyEvaluator + include RubyGenerator + end + + + ## + ## fast engine for Ruby + ## + class FastEruby < Eruby + include InterpolationEnhancer + end + + + ## + ## swtich '<%= %>' to escaped and '<%== %>' to not escaped + ## + class EscapedEruby < Eruby + include EscapeEnhancer + end + + + ## + ## sanitize expression (<%= ... %>) by default + ## + ## this is equivalent to EscapedEruby and is prepared only for compatibility. + ## + class XmlEruby < Eruby + include EscapeEnhancer + end + + + class PI::Eruby < PI::Engine + include RubyEvaluator + include RubyGenerator + + def init_converter(properties={}) + @pi = 'rb' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/escheme.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/escheme.rb new file mode 100644 index 0000000..3f00428 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/escheme.rb @@ -0,0 +1,114 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/engine' +require 'erubis/enhancer' + + +module Erubis + + + module SchemeGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [ + [:func, '_add', "function name (ex. 'display')"], + ] + end + + def init_generator(properties={}) + super + @escapefunc ||= 'escape' + @func = properties[:func] || '_add' # or 'display' + end + + def add_preamble(src) + return unless @func == '_add' + src << "(let ((_buf '())) " + \ + "(define (_add x) (set! _buf (cons x _buf))) " + #src << "(let* ((_buf '())" + \ + # " (_add (lambda (x) (set! _buf (cons x _buf))))) " + end + + def escape_text(text) + @table_ ||= { '"'=>'\\"', '\\'=>'\\\\' } + text.gsub!(/["\\]/) { |m| @table_[m] } + return text + end + + def escaped_expr(code) + code.strip! + return "(#{@escapefunc} #{code})" + end + + def add_text(src, text) + return if text.empty? + t = escape_text(text) + if t[-1] == ?\n + t[-1, 1] = '' + src << "(#{@func} \"" << t << "\\n\")\n" + else + src << "(#{@func} \"" << t << '")' + end + end + + def add_stmt(src, code) + src << code + end + + def add_expr_literal(src, code) + code.strip! + src << "(#{@func} #{code})" + end + + def add_expr_escaped(src, code) + add_expr_literal(src, escaped_expr(code)) + end + + def add_expr_debug(src, code) + s = (code.strip! || code).gsub(/\"/, '\\"') + src << "(display \"*** debug: #{s}=\")(display #{code.strip})(display \"\\n\")" + end + + def add_postamble(src) + return unless @func == '_add' + src << "\n" unless src[-1] == ?\n + src << " (reverse _buf))\n" + end + + end + + + ## + ## engine for Scheme + ## + class Escheme < Basic::Engine + include SchemeGenerator + end + + + class EscapedEscheme < Escheme + include EscapeEnhancer + end + + + #class XmlEscheme < Escheme + # include EscapeEnhancer + #end + + + class PI::Escheme < PI::Engine + include SchemeGenerator + + def init_converter(properties={}) + @pi = 'scheme' + super(properties) + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/optimized.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/optimized.rb new file mode 100644 index 0000000..593e14f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/engine/optimized.rb @@ -0,0 +1,127 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +require 'erubis/engine/eruby' + + +module Erubis + + + module OptimizedGenerator + include Generator + + def self.supported_properties() # :nodoc: + return [] + end + + def init_generator(properties={}) + super + @escapefunc ||= "Erubis::XmlHelper.escape_xml" + @initialized = false + @prev_is_expr = false + end + + protected + + def escape_text(text) + text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\' + end + + def escaped_expr(code) + @escapefunc ||= 'Erubis::XmlHelper.escape_xml' + return "#{@escapefunc}(#{code})" + end + + def switch_to_expr(src) + return if @prev_is_expr + @prev_is_expr = true + src << ' _buf' + end + + def switch_to_stmt(src) + return unless @prev_is_expr + @prev_is_expr = false + src << ';' + end + + def add_preamble(src) + #@initialized = false + #@prev_is_expr = false + end + + def add_text(src, text) + return if text.empty? + if @initialized + switch_to_expr(src) + src << " << '" << escape_text(text) << "'" + else + src << "_buf = '" << escape_text(text) << "';" + @initialized = true + end + end + + def add_stmt(src, code) + switch_to_stmt(src) if @initialized + #super + src << code + src << ';' unless code[-1] == ?\n + end + + def add_expr_literal(src, code) + unless @initialized; src << "_buf = ''"; @initialized = true; end + switch_to_expr(src) + src << " << (" << code << ").to_s" + end + + def add_expr_escaped(src, code) + unless @initialized; src << "_buf = ''"; @initialized = true; end + switch_to_expr(src) + src << " << " << escaped_expr(code) + end + + def add_expr_debug(src, code) + code.strip! + s = (code.dump =~ /\A"(.*)"\z/) && $1 + src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");' + end + + def add_postamble(src) + #super if @initialized + src << "\n_buf\n" if @initialized + end + + end # end of class OptimizedEruby + + + ## + ## Eruby class which generates optimized ruby code + ## + class OptimizedEruby < Basic::Engine # Eruby + include RubyEvaluator + include OptimizedGenerator + + def init_converter(properties={}) + @pi = 'rb' + super(properties) + end + + end + + + ## + ## XmlEruby class which generates optimized ruby code + ## + class OptimizedXmlEruby < OptimizedEruby + include EscapeEnhancer + + def add_expr_debug(src, code) + switch_to_stmt(src) if indicator == '===' && !@initialized + super + end + + end # end of class OptimizedXmlEruby + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/enhancer.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/enhancer.rb new file mode 100644 index 0000000..9cece57 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/enhancer.rb @@ -0,0 +1,723 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +module Erubis + + + ## + ## switch '<%= ... %>' to escaped and '<%== ... %>' to unescaped + ## + ## ex. + ## class XmlEruby < Eruby + ## include EscapeEnhancer + ## end + ## + ## this is language-indenedent. + ## + module EscapeEnhancer + + def self.desc # :nodoc: + "switch '<%= %>' to escaped and '<%== %>' to unescaped" + end + + #-- + #def self.included(klass) + # klass.class_eval <<-END + # alias _add_expr_literal add_expr_literal + # alias _add_expr_escaped add_expr_escaped + # alias add_expr_literal _add_expr_escaped + # alias add_expr_escaped _add_expr_literal + # END + #end + #++ + + def add_expr(src, code, indicator) + case indicator + when '=' + @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code) + when '==' + @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code) + when '===' + add_expr_debug(src, code) + end + end + + end + + + #-- + ## (obsolete) + #module FastEnhancer + #end + #++ + + + ## + ## use $stdout instead of string + ## + ## this is only for Eruby. + ## + module StdoutEnhancer + + def self.desc # :nodoc: + "use $stdout instead of array buffer or string buffer" + end + + def add_preamble(src) + src << "#{@bufvar} = $stdout;" + end + + def add_postamble(src) + src << "\n''\n" + end + + end + + + ## + ## use print statement instead of '_buf << ...' + ## + ## this is only for Eruby. + ## + module PrintOutEnhancer + + def self.desc # :nodoc: + "use print statement instead of '_buf << ...'" + end + + def add_preamble(src) + end + + def add_text(src, text) + src << " print '#{escape_text(text)}';" unless text.empty? + end + + def add_expr_literal(src, code) + src << " print((#{code}).to_s);" + end + + def add_expr_escaped(src, code) + src << " print #{escaped_expr(code)};" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + end + + end + + + ## + ## enable print function + ## + ## Notice: use Eruby#evaluate() and don't use Eruby#result() + ## to be enable print function. + ## + ## this is only for Eruby. + ## + module PrintEnabledEnhancer + + def self.desc # :nodoc: + "enable to use print function in '<% %>'" + end + + def add_preamble(src) + src << "@_buf = " + super + end + + def print(*args) + args.each do |arg| + @_buf << arg.to_s + end + end + + def evaluate(context=nil) + _src = @src + if context.is_a?(Hash) + context.each do |key, val| instance_variable_set("@#{key}", val) end + elsif context + context.instance_variables.each do |name| + instance_variable_set(name, context.instance_variable_get(name)) + end + end + return instance_eval(_src, (@filename || '(erubis)')) + end + + end + + + ## + ## return array instead of string + ## + ## this is only for Eruby. + ## + module ArrayEnhancer + + def self.desc # :nodoc: + "return array instead of string" + end + + def add_preamble(src) + src << "#{@bufvar} = [];" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}\n" + end + + end + + + ## + ## use an Array object as buffer (included in Eruby by default) + ## + ## this is only for Eruby. + ## + module ArrayBufferEnhancer + + def self.desc # :nodoc: + "use an Array object for buffering (included in Eruby class)" + end + + def add_preamble(src) + src << "_buf = [];" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "_buf.join\n" + end + + end + + + ## + ## use String class for buffering + ## + ## this is only for Eruby. + ## + module StringBufferEnhancer + + def self.desc # :nodoc: + "use a String object for buffering" + end + + def add_preamble(src) + src << "#{@bufvar} = '';" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}.to_s\n" + end + + end + + + ## + ## use StringIO class for buffering + ## + ## this is only for Eruby. + ## + module StringIOEnhancer # :nodoc: + + def self.desc # :nodoc: + "use a StringIO object for buffering" + end + + def add_preamble(src) + src << "#{@bufvar} = StringIO.new;" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}.string\n" + end + + end + + + ## + ## set buffer variable name to '_erbout' as well as '_buf' + ## + ## this is only for Eruby. + ## + module ErboutEnhancer + + def self.desc # :nodoc: + "set '_erbout = _buf = \"\";' to be compatible with ERB." + end + + def add_preamble(src) + src << "_erbout = #{@bufvar} = '';" + end + + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "#{@bufvar}.to_s\n" + end + + end + + + ## + ## remove text and leave code, especially useful when debugging. + ## + ## ex. + ## $ erubis -s -E NoText file.eruby | more + ## + ## this is language independent. + ## + module NoTextEnhancer + + def self.desc # :nodoc: + "remove text and leave code (useful when debugging)" + end + + def add_text(src, text) + src << ("\n" * text.count("\n")) + if text[-1] != ?\n + text =~ /^(.*?)\z/ + src << (' ' * $1.length) + end + end + + end + + + ## + ## remove code and leave text, especially useful when validating HTML tags. + ## + ## ex. + ## $ erubis -s -E NoCode file.eruby | tidy -errors + ## + ## this is language independent. + ## + module NoCodeEnhancer + + def self.desc # :nodoc: + "remove code and leave text (useful when validating HTML)" + end + + def add_preamble(src) + end + + def add_postamble(src) + end + + def add_text(src, text) + src << text + end + + def add_expr(src, code, indicator) + src << "\n" * code.count("\n") + end + + def add_stmt(src, code) + src << "\n" * code.count("\n") + end + + end + + + ## + ## get convert faster, but spaces around '<%...%>' are not trimmed. + ## + ## this is language-independent. + ## + module SimplifyEnhancer + + def self.desc # :nodoc: + "get convert faster but leave spaces around '<% %>'" + end + + #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m + SIMPLE_REGEXP = /<%(=+|\#)?(.*?)-?%>/m + + def convert(input) + src = "" + add_preamble(src) + #regexp = pattern_regexp(@pattern) + pos = 0 + input.scan(SIMPLE_REGEXP) do |indicator, code| + match = Regexp.last_match + index = match.begin(0) + text = input[pos, index - pos] + pos = match.end(0) + add_text(src, text) + if !indicator # <% %> + add_stmt(src, code) + elsif indicator[0] == ?\# # <%# %> + n = code.count("\n") + add_stmt(src, "\n" * n) + else # <%= %> + add_expr(src, code, indicator) + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(src, rest) + add_postamble(src) + return src + end + + end + + + ## + ## enable to use other embedded expression pattern (default is '\[= =\]'). + ## + ## notice! this is an experimental. spec may change in the future. + ## + ## ex. + ## input = < + ## <%= item %> : <%== item %> + ## [= item =] : [== item =] + ## <% end %> + ## END + ## + ## class BiPatternEruby + ## include BiPatternEnhancer + ## end + ## eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]') + ## list = ['', 'b&b', '"c"'] + ## print eruby.result(binding()) + ## + ## ## output + ## : <a> + ## : <a> + ## b&b : b&b + ## b&b : b&b + ## "c" : "c" + ## "c" : "c" + ## + ## this is language independent. + ## + module BiPatternEnhancer + + def self.desc # :nodoc: + "another embedded expression pattern (default '\[= =\]')." + end + + def initialize(input, properties={}) + self.bipattern = properties[:bipattern] # or '\$\{ \}' + super + end + + ## when pat is nil then '\[= =\]' is used + def bipattern=(pat) # :nodoc: + @bipattern = pat || '\[= =\]' + pre, post = @bipattern.split() + @bipattern_regexp = /(.*?)#{pre}(=*)(.*?)#{post}/m + end + + def add_text(src, text) + return unless text + m = nil + text.scan(@bipattern_regexp) do |txt, indicator, code| + m = Regexp.last_match + super(src, txt) + add_expr(src, code, '=' + indicator) + end + #rest = $' || text # ruby1.8 + rest = m ? text[m.end(0)..-1] : text # ruby1.9 + super(src, rest) + end + + end + + + ## + ## regards lines starting with '^[ \t]*%' as program code + ## + ## in addition you can specify prefix character (default '%') + ## + ## this is language-independent. + ## + module PrefixedLineEnhancer + + def self.desc # :nodoc: + "regard lines matched to '^[ \t]*%' as program code" + end + + def init_generator(properties={}) + super + @prefixchar = properties[:prefixchar] + end + + def add_text(src, text) + unless @prefixrexp + @prefixchar ||= '%' + @prefixrexp = Regexp.compile("^([ \\t]*)\\#{@prefixchar}(.*?\\r?\\n)") + end + pos = 0 + text2 = '' + text.scan(@prefixrexp) do + space = $1 + line = $2 + space, line = '', $1 unless $2 + match = Regexp.last_match + len = match.begin(0) - pos + str = text[pos, len] + pos = match.end(0) + if text2.empty? + text2 = str + else + text2 << str + end + if line[0, 1] == @prefixchar + text2 << space << line + else + super(src, text2) + text2 = '' + add_stmt(src, space + line) + end + end + #rest = pos == 0 ? text : $' # ruby1.8 + rest = pos == 0 ? text : text[pos..-1] # ruby1.9 + unless text2.empty? + text2 << rest if rest + rest = text2 + end + super(src, rest) + end + + end + + + ## + ## regards lines starting with '%' as program code + ## + ## this is for compatibility to eruby and ERB. + ## + ## this is language-independent. + ## + module PercentLineEnhancer + include PrefixedLineEnhancer + + def self.desc # :nodoc: + "regard lines starting with '%' as program code" + end + + #-- + #def init_generator(properties={}) + # super + # @prefixchar = '%' + # @prefixrexp = /^\%(.*?\r?\n)/ + #end + #++ + + def add_text(src, text) + unless @prefixrexp + @prefixchar = '%' + @prefixrexp = /^\%(.*?\r?\n)/ + end + super(src, text) + end + + end + + + ## + ## [experimental] allow header and footer in eRuby script + ## + ## ex. + ## ==================== + ## ## without header and footer + ## $ cat ex1.eruby + ## <% def list_items(list) %> + ## <% for item in list %> + ##
  • <%= item %>
  • + ## <% end %> + ## <% end %> + ## + ## $ erubis -s ex1.eruby + ## _buf = []; def list_items(list) + ## ; for item in list + ## ; _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • + ## '; end + ## ; end + ## ; + ## _buf.join + ## + ## ## with header and footer + ## $ cat ex2.eruby + ## + ## <% for item in list %> + ##
  • <%= item %>
  • + ## <% end %> + ## + ## + ## $ erubis -s -c HeaderFooterEruby ex4.eruby + ## + ## def list_items(list) + ## _buf = []; _buf << ' + ## '; for item in list + ## ; _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • + ## '; end + ## ; _buf << ' + ## '; + ## _buf.join + ## end + ## + ## ==================== + ## + ## this is language-independent. + ## + module HeaderFooterEnhancer + + def self.desc # :nodoc: + "allow header/footer in document (ex. '')" + end + + HEADER_FOOTER_PATTERN = /(.*?)(^[ \t]*)?([ \t]*\r?\n)?/m + + def add_text(src, text) + m = nil + text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace| + m = Regexp.last_match + flag_trim = @trim && lspace && rspace + super(src, txt) + content = "#{lspace}#{content}#{rspace}" if flag_trim + super(src, lspace) if !flag_trim && lspace + instance_variable_set("@#{word}", content) + super(src, rspace) if !flag_trim && rspace + end + #rest = $' || text # ruby1.8 + rest = m ? text[m.end(0)..-1] : text # ruby1.9 + super(src, rest) + end + + attr_accessor :header, :footer + + def convert(input) + source = super + return @src = "#{@header}#{source}#{@footer}" + end + + end + + + ## + ## delete indentation of HTML. + ## + ## this is language-independent. + ## + module DeleteIndentEnhancer + + def self.desc # :nodoc: + "delete indentation of HTML." + end + + def convert_input(src, input) + input = input.gsub(/^[ \t]+<%=title%>" into "_buf << %Q`

    #{title}

    `" + ## + ## this is only for Eruby. + ## + module InterpolationEnhancer + + def self.desc # :nodoc: + "convert '

    <%=text%>

    ' into '_buf << %Q`

    \#{text}

    `'" + end + + def convert_input(src, input) + pat = @pattern + regexp = pat.nil? || pat == '<% %>' ? Basic::Converter::DEFAULT_REGEXP : pattern_regexp(pat) + pos = 0 + is_bol = true # is beginning of line + str = '' + input.scan(regexp) do |indicator, code, tailch, rspace| + match = Regexp.last_match() + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + ch = indicator ? indicator[0] : nil + lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol) + is_bol = rspace ? true : false + _add_text_to_str(str, text) + ## * when '<%= %>', do nothing + ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>' + if ch == ?= # <%= %> + rspace = nil if tailch && !tailch.empty? + str << lspace if lspace + add_expr(str, code, indicator) + str << rspace if rspace + elsif ch == ?\# # <%# %> + n = code.count("\n") + (rspace ? 1 : 0) + if @trim && lspace && rspace + add_text(src, str) + str = '' + add_stmt(src, "\n" * n) + else + str << lspace if lspace + add_text(src, str) + str = '' + add_stmt(src, "\n" * n) + str << rspace if rspace + end + else # <% %> + if @trim && lspace && rspace + add_text(src, str) + str = '' + add_stmt(src, "#{lspace}#{code}#{rspace}") + else + str << lspace if lspace + add_text(src, str) + str = '' + add_stmt(src, code) + str << rspace if rspace + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + _add_text_to_str(str, rest) + add_text(src, str) + end + + def add_text(src, text) + return if !text || text.empty? + #src << " _buf << %Q`" << text << "`;" + if text[-1] == ?\n + text[-1] = "\\n" + src << " #{@bufvar} << %Q`#{text}`\n" + else + src << " #{@bufvar} << %Q`#{text}`;" + end + end + + def _add_text_to_str(str, text) + return if !text || text.empty? + str << text.gsub(/[`\#\\]/, '\\\\\&') + end + + def add_expr_escaped(str, code) + str << "\#{#{escaped_expr(code)}}" + end + + def add_expr_literal(str, code) + str << "\#{#{code}}" + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/error.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/error.rb new file mode 100644 index 0000000..6576963 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/error.rb @@ -0,0 +1,23 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +module Erubis + + + ## + ## base error class + ## + class ErubisError < StandardError + end + + + ## + ## raised when method or function is not supported + ## + class NotSupportedError < ErubisError + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/evaluator.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/evaluator.rb new file mode 100644 index 0000000..688b821 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/evaluator.rb @@ -0,0 +1,88 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/error' +require 'erubis/context' + + +module Erubis + + EMPTY_BINDING = binding() + + + ## + ## evaluate code + ## + module Evaluator + + def self.supported_properties # :nodoc: + return [] + end + + attr_accessor :src, :filename + + def init_evaluator(properties) + @filename = properties[:filename] + end + + def result(*args) + raise NotSupportedError.new("evaluation of code except Ruby is not supported.") + end + + def evaluate(*args) + raise NotSupportedError.new("evaluation of code except Ruby is not supported.") + end + + end + + + ## + ## evaluator for Ruby + ## + module RubyEvaluator + include Evaluator + + def self.supported_properties # :nodoc: + list = Evaluator.supported_properties + return list + end + + ## eval(@src) with binding object + def result(_binding_or_hash=TOPLEVEL_BINDING) + _arg = _binding_or_hash + if _arg.is_a?(Hash) + _b = binding() + eval _arg.collect{|k,v| "#{k} = _arg[#{k.inspect}]; "}.join, _b + elsif _arg.is_a?(Binding) + _b = _arg + elsif _arg.nil? + _b = binding() + else + raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.") + end + return eval(@src, _b, (@filename || '(erubis')) + end + + ## invoke context.instance_eval(@src) + def evaluate(_context=Context.new) + _context = Context.new(_context) if _context.is_a?(Hash) + #return _context.instance_eval(@src, @filename || '(erubis)') + #@_proc ||= eval("proc { #{@src} }", Erubis::EMPTY_BINDING, @filename || '(erubis)') + @_proc ||= eval("proc { #{@src} }", binding(), @filename || '(erubis)') + return _context.instance_eval(&@_proc) + end + + ## if object is an Class or Module then define instance method to it, + ## else define singleton method to it. + def def_method(object, method_name, filename=nil) + m = object.is_a?(Module) ? :module_eval : :instance_eval + object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(erubis)') + end + + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/generator.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/generator.rb new file mode 100644 index 0000000..b9335fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/generator.rb @@ -0,0 +1,85 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require 'erubis/util' + +module Erubis + + + ## + ## code generator, called by Converter module + ## + module Generator + + def self.supported_properties() # :nodoc: + return [ + [:escapefunc, nil, "escape function name"], + ] + end + + attr_accessor :escapefunc + + def init_generator(properties={}) + @escapefunc = properties[:escapefunc] + end + + + ## (abstract) escape text string + ## + ## ex. + ## def escape_text(text) + ## return text.dump + ## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'" + ## end + def escape_text(text) + not_implemented + end + + ## return escaped expression code (ex. 'h(...)' or 'htmlspecialchars(...)') + def escaped_expr(code) + code.strip! + return "#{@escapefunc}(#{code})" + end + + ## (abstract) add @preamble to src + def add_preamble(src) + not_implemented + end + + ## (abstract) add text string to src + def add_text(src, text) + not_implemented + end + + ## (abstract) add statement code to src + def add_stmt(src, code) + not_implemented + end + + ## (abstract) add expression literal code to src. this is called by add_expr(). + def add_expr_literal(src, code) + not_implemented + end + + ## (abstract) add escaped expression code to src. this is called by add_expr(). + def add_expr_escaped(src, code) + not_implemented + end + + ## (abstract) add expression code to src for debug. this is called by add_expr(). + def add_expr_debug(src, code) + not_implemented + end + + ## (abstract) add @postamble to src + def add_postamble(src) + not_implemented + end + + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helper.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helper.rb new file mode 100644 index 0000000..1a24c58 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helper.rb @@ -0,0 +1,47 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +module Erubis + + ## + ## helper for xml + ## + module XmlHelper + + module_function + + ESCAPE_TABLE = { + '&' => '&', + '<' => '<', + '>' => '>', + '"' => '"', + "'" => ''', + } + + def escape_xml(value) + value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/ + #value.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] } + end + + def escape_xml2(value) + return value.to_s.gsub(/\&/,'&').gsub(//,'>').gsub(/"/,'"') + end + + alias h escape_xml + alias html_escape escape_xml + + def url_encode(str) + return str.gsub(/[^-_.a-zA-Z0-9]+/) { |s| + s.unpack('C*').collect { |i| "%%%02X" % i }.join + } + end + + alias u url_encode + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helpers/rails_form_helper.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helpers/rails_form_helper.rb new file mode 100644 index 0000000..945698b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helpers/rails_form_helper.rb @@ -0,0 +1,197 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + + +module Erubis + module Helpers + module RailsFormHelper + end + end +end + + +module Erubis::Helpers::RailsFormHelper + + +if ActionPack::VERSION::MAJOR == 1 ### Rails 1.X + def pp_template_filename(basename) + return "#{RAILS_ROOT}/app/views/#{controller.controller_name}/#{basename}.rhtml" + end +else ### Rails 2.X + def pp_template_filename(basename) + fname = "#{RAILS_ROOT}/app/views/#{controller.controller_name}/#{basename}.html.erb" + return fname if test(?f, fname) + return "#{RAILS_ROOT}/app/views/#{controller.controller_name}/#{basename}.rhtml" + end +end + + def pp_render_partial(basename) + basename = "_#{basename}" unless basename[0] == ?_ + filename = pp_template_filename(basename) + preprocessor = _create_preprocessor(File.read(filename)) + return preprocessor.evaluate(_preprocessing_context_object()) + end + + def pp_error_on(object_name, method) + s = '' + s << "<% _stag, _etag = _pp_error_tags(@#{object_name}.errors.on('#{method}')) %>" + s << "<%= _stag %>" + s << yield(object_name, method) + s << "<%= _etag %>" + return s + end + + def _pp_error_tags(value) + return value ? ['
    ', '
    '] : ['', ''] + end + + def _pp_remove_error_div(s) + s.sub!(/\A
    (.*)<\/div>\z/, '\1') + return s + end + + def pp_tag_helper(helper, object_name, method, options={}) + if object_name.is_a?(ActionView::Helpers::FormHelper) + object_name = object_name.object_name + end + unless options.key?(:value) || options.key?('value') + options['value'] = _?("h @#{object_name}.#{method}") + end + #$stderr.puts "*** debug: pp_tag_helper(): options=#{options.inspect}" + return pp_error_on(object_name, method) { + s = __send__(helper, object_name, method, options) + _pp_remove_error_div(s) + } + end + + def pp_form_tag(url_for_options={}, options={}, *parameters_for_url, &block) + return form_tag(url_for_options, options, *parameters_for_url, &block) + end + + #-- + #def pp_form_for(object_name, *args, &block) + # return form_for(object_name, *args, &block) + #end + #++ + + def pp_text_field(object_name, method, options={}) + return pp_tag_helper(:text_field, object_name, method, options) + end + + def pp_password_field(object_name, method, options={}) + return pp_tag_helper(:password_field, object_name, method, options) + end + + def pp_hidden_field(object_name, method, options={}) + return pp_tag_helper(:hidden_field, object_name, method, options) + end + + def pp_file_field(object_name, method, options={}) + return pp_tag_helper(:file_field, object_name, method, options) + end + + def pp_text_area(object_name, method, options={}) + return pp_tag_helper(:text_area, object_name, method, options) + end + + def pp_check_box(object_name, method, options={}, checked_value="1", unchecked_value="0") + s = check_box(object_name, method, options, checked_value, unchecked_value) + s.sub!(/\schecked=\"checked\"/, '') + s.sub!(/type="checkbox"/, "\\&<%= _pp_check_box_checked?(@#{object_name}.#{method}, #{checked_value.inspect}) ? ' checked=\"checked\"' : '' %>") + return pp_error_on(object_name, method) { _pp_remove_error_div(s) } + end + + def _pp_check_box_checked?(value, checked_value) + return ActionView::Helpers::InstanceTag::check_box_checked?(value, checked_value) + end + + def pp_radio_button(object_name, method, tag_value, options={}) + s = radio_button(object_name, method, tag_value, options) + s.sub!(/\schecked=\"checked\"/, '') + s.sub!(/type="radio"/, "\\&<%= _pp_radio_button_checked?(@#{object_name}.#{method}, #{tag_value.inspect}) ? ' checked=\"checked\"' : '' %>") + return pp_error_on(object_name, method) { _pp_remove_error_div(s) } + end + + def _pp_radio_button_checked?(value, tag_value) + return ActionView::Helpers::InstanceTag::radio_button_checked?(value, tag_value) + end + + def _pp_select(object, method, collection, priority_collection, options={}, html_options={}) + return pp_error_on(object, method) do + s = "" + ## start tag + s << "" + s + end + end + + def _pp_select_options(s, collection, selected, operator) + for item in collection + value, text = item.is_a?(Array) ? item : [item, item] + if !selected + t = '' + elsif operator == 'delete' + t = "<%= _table.delete(#{value.inspect}) %>" + else + t = "<%= _table[#{value.inspect}] %>" + end + s << "\n" + end + end + + def pp_select(object, method, collection, options={}, html_options={}) + return _pp_select(object, method, collection, nil, options, html_options) + end + + def pp_collection_select(object, method, collection, value_method, text_method, options={}, html_options={}) + collection2 = collection.collect { |e| + [e.__send__(value_method), e.__send__(text_method)] + } + return _pp_select(object, method, collection2, nil, options, html_options) + end + + def pp_country_select(object, method, priority_countries=nil, options={}, html_options={}) + collection = ActionView::Helpers::FormOptionsHelper::COUNTRIES + return _pp_select(object, method, collection, priority_countries, options, html_options) + end + + def pp_time_zone_select(object, method, priority_zones=nil, options={}, html_options={}) + model = options[:model] || options['model'] || TimeZone + collection = model.all.collect { |e| [e.name, e.to_s] } + return _pp_select(object, method, collection, priority_zones, options, html_options) + end + + def pp_submit_tag(value="Save changes", options={}) + return submit_tag(value, options) + end + + def pp_image_submit_tag(source, options={}) + return image_submit_tag(source, options) + end + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helpers/rails_helper.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helpers/rails_helper.rb new file mode 100644 index 0000000..1c89c9b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/helpers/rails_helper.rb @@ -0,0 +1,353 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + + +require 'erubis' +require 'erubis/preprocessing' + + +module Erubis + + class Eruby + include ErboutEnhancer # will generate '_erbout = _buf = ""; ' + end + + class FastEruby + include ErboutEnhancer # will generate '_erbout = _buf = ""; ' + end + + module Helpers + + ## + ## helper module for Ruby on Rails + ## + ## howto: + ## + ## 1. add the folliwng code in your 'config/environment.rb' + ## + ## require 'erubis/helpers/rails_helper' + ## #Erubis::Helpers::RailsHelper.engine_class = Erubis::Eruby # or Erubis::FastEruby + ## #Erubis::Helpers::RailsHelper.init_properties = {} + ## #Erubis::Helpers::RailsHelper.show_src = false # set true for debugging + ## #Erubis::Helpers::RailsHelper.preprocessing = true # set true to enable preprocessing + ## + ## 2. restart web server. + ## + ## if Erubis::Helper::Rails.show_src is true, Erubis prints converted Ruby code + ## into log file ('log/development.log' or so). if false, it doesn't. + ## if nil, Erubis prints converted Ruby code if ENV['RAILS_ENV'] == 'development'. + ## + module RailsHelper + + #cattr_accessor :init_properties + @@engine_class = ::Erubis::Eruby + #@@engine_class = ::Erubis::FastEruby + def self.engine_class + @@engine_class + end + def self.engine_class=(klass) + @@engine_class = klass + end + + #cattr_accessor :init_properties + @@init_properties = {} + def self.init_properties + @@init_properties + end + def self.init_properties=(hash) + @@init_properties = hash + end + + #cattr_accessor :show_src + @@show_src = nil + def self.show_src + @@show_src + end + def self.show_src=(flag) + @@show_src = flag + end + + #cattr_accessor :preprocessing + @@preprocessing = false + def self.preprocessing + @@preprocessing + end + def self.preprocessing=(flag) + @@preprocessing = flag + end + + + ## define class for backward-compatibility + class PreprocessingEruby < Erubis::PreprocessingEruby # :nodoc: + end + + + module TemplateConverter + ## covert eRuby string into ruby code + def _convert_template(template) # :nodoc: + #src = ::Erubis::Eruby.new(template).src + klass = ::Erubis::Helpers::RailsHelper.engine_class + properties = ::Erubis::Helpers::RailsHelper.init_properties + show_src = ::Erubis::Helpers::RailsHelper.show_src + show_src = ENV['RAILS_ENV'] == 'development' if show_src.nil? + ## preprocessing + if ::Erubis::Helpers::RailsHelper.preprocessing + preprocessor = _create_preprocessor(template) + template = preprocessor.evaluate(_preprocessing_context_object()) + _logger_info "** Erubis: preprocessed==<<'END'\n#{template}END\n" if show_src + end + ## convert into ruby code + src = klass.new(template, properties).src + #src.insert(0, '_erbout = ') + _logger_info "** Erubis: src==<<'END'\n#{src}END\n" if show_src + return src + end + def _create_preprocessor(template) + return PreprocessingEruby.new(template, :escape=>true) + end + def _preprocessing_context_object + return self + end + def _logger_info(message) + logger.info message + end + end + + end + + end + +end + + +class ActionView::Base # :nodoc: + include ::Erubis::Helpers::RailsHelper::TemplateConverter + include ::Erubis::PreprocessingHelper + private + # convert template into ruby code + def convert_template_into_ruby_code(template) + #ERB.new(template, nil, @@erb_trim_mode).src + return _convert_template(template) + end +end + + +require 'action_pack/version' + +rails22 = false + +if ActionPack::VERSION::MAJOR >= 2 ### Rails 2.X + + + if ActionPack::VERSION::MINOR >=2 ### Rails 2.2, 2.3 or higher + + rails22 = true + module ActionView + module TemplateHandlers + class ErubisHandler < TemplateHandler + include Compilable + include ::Erubis::Helpers::RailsHelper::TemplateConverter + include ::Erubis::PreprocessingHelper + def compile(template) + #src = ::ERB.new("<% __in_erb_template=true %>#{template.source}", nil, erb_trim_mode, '@output_buffer').src + return _convert_template("<% __in_erb_template=true %>#{template.source}") + end + end + end + handler_klass = TemplateHandlers::ErubisHandler + Template.register_default_template_handler :erb, handler_klass + Template.register_template_handler :rhtml, handler_klass + end + module Erubis::Helpers::RailsHelper::TemplateConverter + def _logger_info(message) + #logger.info message # logger.info seems not available in Rails 2.2 + ActionController::Base.new.logger.info message + end + end + + elsif ActionPack::VERSION::MINOR >=1 ### Rails 2.1 + + module ActionView + module TemplateHandlers # :nodoc: + class ErubisHandler < TemplateHandler + include Compilable + include Erubis::Helpers::RailsHelper::TemplateConverter + include Erubis::PreprocessingHelper + # + def compile(template) + return _convert_template(template.source) # template.is_a?(ActionView::Template) + end + def logger #:nodoc: + return @view.controller.logger + end + def _preprocessing_context_object #:nodoc: + return @view.controller.instance_variable_get('@template') + end + # + def cache_fragment(block, name = {}, options = nil) #:nodoc: + @view.fragment_for(block, name, options) do + #eval(ActionView::Base.erb_variable, block.binding) + eval('_buf', block.binding) + end + end + end + end + handler_klass = TemplateHandlers::ErubisHandler + Template.register_default_template_handler :erb, handler_klass + Template.register_template_handler :rhtml, handler_klass + end + + elsif ActionPack::VERSION::TINY >= 2 ### Rails 2.0.X (X >= 2) + + module ActionView + module TemplateHandlers # :nodoc: + class ErubisHandler < TemplateHandler + include Erubis::Helpers::RailsHelper::TemplateConverter + include Erubis::PreprocessingHelper + def compile(template) + return _convert_template(template) # template.is_a?(String) + end + def logger #:nodoc: + return @view.controller.logger + end + def _preprocessing_context_object #:nodoc: + return @view.controller.instance_variable_get('@template') + end + end + end + Base.class_eval do + handler_klass = TemplateHandlers::ErubisHandler + register_default_template_handler :erb, handler_klass + register_template_handler :rhtml, handler_klass + end + end + + else ### Rails 2.0.0 or 2.0.1 + + class ActionView::Base # :nodoc: + private + # Method to create the source code for a given template. + def create_template_source(extension, template, render_symbol, locals) + if template_requires_setup?(extension) + body = case extension.to_sym + when :rxml, :builder + content_type_handler = (controller.respond_to?(:response) ? "controller.response" : "controller") + "#{content_type_handler}.content_type ||= Mime::XML\n" + + "xml = Builder::XmlMarkup.new(:indent => 2)\n" + + template + + "\nxml.target!\n" + when :rjs + "controller.response.content_type ||= Mime::JS\n" + + "update_page do |page|\n#{template}\nend" + end + else + #body = ERB.new(template, nil, @@erb_trim_mode).src + body = convert_template_into_ruby_code(template) + end + # + @@template_args[render_symbol] ||= {} + locals_keys = @@template_args[render_symbol].keys | locals + @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } + # + locals_code = "" + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}]\n" + end + # + "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" + end + end + + end #if + + +else ### Rails 1.X + + + if ActionPack::VERSION::MINOR > 12 ### Rails 1.2 + + class ActionView::Base # :nodoc: + private + # Create source code for given template + def create_template_source(extension, template, render_symbol, locals) + if template_requires_setup?(extension) + body = case extension.to_sym + when :rxml + "controller.response.content_type ||= 'application/xml'\n" + + "xml = Builder::XmlMarkup.new(:indent => 2)\n" + + template + when :rjs + "controller.response.content_type ||= 'text/javascript'\n" + + "update_page do |page|\n#{template}\nend" + end + else + #body = ERB.new(template, nil, @@erb_trim_mode).src + body = convert_template_into_ruby_code(template) + end + # + @@template_args[render_symbol] ||= {} + locals_keys = @@template_args[render_symbol].keys | locals + @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } + # + locals_code = "" + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}]\n" + end + # + "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" + end + end + + else ### Rails 1.1 + + class ActionView::Base # :nodoc: + private + # Create source code for given template + def create_template_source(extension, template, render_symbol, locals) + if template_requires_setup?(extension) + body = case extension.to_sym + when :rxml + "xml = Builder::XmlMarkup.new(:indent => 2)\n" + + "@controller.headers['Content-Type'] ||= 'application/xml'\n" + + template + when :rjs + "@controller.headers['Content-Type'] ||= 'text/javascript'\n" + + "update_page do |page|\n#{template}\nend" + end + else + #body = ERB.new(template, nil, @@erb_trim_mode).src + body = convert_template_into_ruby_code(template) + end + # + @@template_args[render_symbol] ||= {} + locals_keys = @@template_args[render_symbol].keys | locals + @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } + # + locals_code = "" + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}] if local_assigns.has_key?(:#{key})\n" + end + # + "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" + end + end + + end #if + + ## make h() method faster (only for Rails 1.X) + module ERB::Util # :nodoc: + ESCAPE_TABLE = { '&'=>'&', '<'=>'<', '>'=>'>', '"'=>'"', "'"=>''', } + def h(value) + value.to_s.gsub(/[&<>"]/) {|s| ESCAPE_TABLE[s] } + end + module_function :h + end + +end ### + + +## finish +ActionController::Base.new.logger.info "** Erubis #{::Erubis::VERSION}" +$stdout.puts "** Erubis #{::Erubis::VERSION}" if rails22 diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/local-setting.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/local-setting.rb new file mode 100644 index 0000000..17fd4ea --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/local-setting.rb @@ -0,0 +1,9 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +## +## you can add site-local settings here. +## this files is required by erubis.rb +## diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/main.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/main.rb new file mode 100644 index 0000000..9997cf9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/main.rb @@ -0,0 +1,516 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'yaml' +require 'erubis' +require 'erubis/tiny' +require 'erubis/engine/enhanced' +require 'erubis/engine/optimized' +require 'erubis/engine/eruby' +require 'erubis/engine/ephp' +require 'erubis/engine/ec' +require 'erubis/engine/ecpp' +require 'erubis/engine/ejava' +require 'erubis/engine/escheme' +require 'erubis/engine/eperl' +require 'erubis/engine/ejavascript' + + +module Erubis + + + Ejs = Ejavascript + EscapedEjs = EscapedEjavascript + + + class CommandOptionError < ErubisError + end + + + ## + ## main class of command + ## + ## ex. + ## Main.main(ARGV) + ## + class Main + + def self.main(argv=ARGV) + status = 0 + begin + Main.new.execute(ARGV) + rescue CommandOptionError => ex + $stderr.puts ex.message + status = 1 + end + exit(status) + end + + def initialize + @single_options = "hvxztTSbeBXNUC" + @arg_options = "pcrfKIlaE" #C + @option_names = { + 'h' => :help, + 'v' => :version, + 'x' => :source, + 'z' => :syntax, + 'T' => :unexpand, + 't' => :untabify, # obsolete + 'S' => :intern, + 'b' => :bodyonly, + 'B' => :binding, + 'p' => :pattern, + 'c' => :context, + #'C' => :class, + 'e' => :escape, + 'r' => :requires, + 'f' => :datafiles, + 'K' => :kanji, + 'I' => :includes, + 'l' => :lang, + 'a' => :action, + 'E' => :enhancers, + 'X' => :notext, + 'N' => :linenum, + 'U' => :unique, + 'C' => :compact, + } + assert unless @single_options.length + @arg_options.length == @option_names.length + (@single_options + @arg_options).each_byte do |ch| + assert unless @option_names.key?(ch.chr) + end + end + + + def execute(argv=ARGV) + ## parse command-line options + options, properties = parse_argv(argv, @single_options, @arg_options) + filenames = argv + options['h'] = true if properties[:help] + opts = Object.new + arr = @option_names.collect {|ch, name| "def #{name}; @#{name}; end\n" } + opts.instance_eval arr.join + options.each do |ch, val| + name = @option_names[ch] + opts.instance_variable_set("@#{name}", val) + end + + ## help, version, enhancer list + if opts.help || opts.version + puts version() if opts.version + puts usage() if opts.help + puts show_properties() if opts.help + puts show_enhancers() if opts.help + return + end + + ## include path + opts.includes.split(/,/).each do |path| + $: << path + end if opts.includes + + ## require library + opts.requires.split(/,/).each do |library| + require library + end if opts.requires + + ## action + action = opts.action + action ||= 'syntax' if opts.syntax + action ||= 'convert' if opts.source || opts.notext + + ## lang + lang = opts.lang || 'ruby' + action ||= 'convert' if opts.lang + + ## class name of Eruby + #classname = opts.class + classname = nil + klass = get_classobj(classname, lang, properties[:pi]) + + ## kanji code + $KCODE = opts.kanji if opts.kanji + + ## read context values from yaml file + datafiles = opts.datafiles + context = load_datafiles(datafiles, opts) + + ## parse context data + if opts.context + context = parse_context_data(opts.context, opts) + end + + ## properties for engine + properties[:escape] = true if opts.escape && !properties.key?(:escape) + properties[:pattern] = opts.pattern if opts.pattern + #properties[:trim] = false if opts.notrim + properties[:preamble] = properties[:postamble] = false if opts.bodyonly + properties[:pi] = nil if properties[:pi] == true + + ## create engine and extend enhancers + engine = klass.new(nil, properties) + enhancers = get_enhancers(opts.enhancers) + #enhancers.push(Erubis::EscapeEnhancer) if opts.escape + enhancers.each do |enhancer| + engine.extend(enhancer) + engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer + end + + ## no-text + engine.extend(Erubis::NoTextEnhancer) if opts.notext + + ## convert and execute + val = nil + msg = "Syntax OK\n" + if filenames && !filenames.empty? + filenames.each do |filename| + File.file?(filename) or + raise CommandOptionError.new("#{filename}: file not found.") + engine.filename = filename + engine.convert!(File.read(filename)) + val = do_action(action, engine, context, filename, opts) + msg = nil if val + end + else + engine.filename = filename = '(stdin)' + engine.convert!($stdin.read()) + val = do_action(action, engine, context, filename, opts) + msg = nil if val + end + print msg if action == 'syntax' && msg + + end + + private + + def do_action(action, engine, context, filename, opts) + case action + when 'convert' + s = manipulate_src(engine.src, opts) + when nil, 'exec', 'execute' + s = opts.binding ? engine.result(context.to_hash) : engine.evaluate(context) + when 'syntax' + s = check_syntax(filename, engine.src) + else + raise "*** internal error" + end + print s if s + return s + end + + def manipulate_src(source, opts) + flag_linenum = opts.linenum + flag_unique = opts.unique + flag_compact = opts.compact + if flag_linenum + n = 0 + source.gsub!(/^/) { n += 1; "%5d: " % n } + source.gsub!(/^ *\d+:\s+?\n/, '') if flag_compact + source.gsub!(/(^ *\d+:\s+?\n)+/, "\n") if flag_unique + else + source.gsub!(/^\s*?\n/, '') if flag_compact + source.gsub!(/(^\s*?\n)+/, "\n") if flag_unique + end + return source + end + + def usage(command=nil) + command ||= File.basename($0) + buf = [] + buf << "erubis - embedded program converter for multi-language" + buf << "Usage: #{command} [..options..] [file ...]" + buf << " -h, --help : help" + buf << " -v : version" + buf << " -x : show converted code" + buf << " -X : show converted code, only ruby code and no text part" + buf << " -N : numbering: add line numbers (for '-x/-X')" + buf << " -U : unique: compress empty lines to a line (for '-x/-X')" + buf << " -C : compact: remove empty lines (for '-x/-X')" + buf << " -b : body only: no preamble nor postamble (for '-x/-X')" + buf << " -z : syntax checking" + buf << " -e : escape (equal to '--E Escape')" + buf << " -p pattern : embedded pattern (default '<% %>')" + buf << " -l lang : convert but no execute (ruby/php/c/cpp/java/scheme/perl/js)" + buf << " -E e1,e2,... : enhancer names (Escape, PercentLine, BiPattern, ...)" + buf << " -I path : library include path" + buf << " -K kanji : kanji code (euc/sjis/utf8) (default none)" + buf << " -c context : context data string (yaml inline style or ruby code)" + buf << " -f datafile : context data file ('*.yaml', '*.yml', or '*.rb')" + #buf << " -t : expand tab characters in YAML file" + buf << " -T : don't expand tab characters in YAML file" + buf << " -S : convert mapping key from string to symbol in YAML file" + buf << " -B : invoke 'result(binding)' instead of 'evaluate(context)'" + buf << " --pi=name : parse '' instead of '<% ... %>'" + #' + # -T : don't trim spaces around '<% %>' + # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby) + # -r library : require library + # -a : action (convert/execute) + return buf.join("\n") + end + + def collect_supported_properties(erubis_klass) + list = [] + erubis_klass.ancestors.each do |klass| + if klass.respond_to?(:supported_properties) + list.concat(klass.supported_properties) + end + end + return list + end + + def show_properties + s = "supported properties:\n" + basic_props = collect_supported_properties(Erubis::Basic::Engine) + pi_props = collect_supported_properties(Erubis::PI::Engine) + list = [] + common_props = basic_props & pi_props + list << ['(common)', common_props] + list << ['(basic)', basic_props - common_props] + list << ['(pi)', pi_props - common_props] + %w[ruby php c cpp java scheme perl javascript].each do |lang| + klass = Erubis.const_get("E#{lang}") + list << [lang, collect_supported_properties(klass) - basic_props] + end + list.each do |lang, props| + s << " * #{lang}\n" + props.each do |name, default_val, desc| + s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc]) + end + end + s << "\n" + return s + end + + def show_enhancers + dict = {} + ObjectSpace.each_object(Module) do |mod| + dict[$1] = mod if mod.name =~ /\AErubis::(.*)Enhancer\z/ + end + s = "enhancers:\n" + dict.sort_by {|name, mod| name }.each do |name, mod| + s << (" %-13s : %s\n" % [name, mod.desc]) + end + return s + end + + def version + return Erubis::VERSION + end + + def parse_argv(argv, arg_none='', arg_required='', arg_optional='') + options = {} + context = {} + while argv[0] && argv[0][0] == ?- + optstr = argv.shift + optstr = optstr[1, optstr.length-1] + # + if optstr[0] == ?- # context + optstr =~ /\A\-([-\w]+)(?:=(.*))?/ or + raise CommandOptionError.new("-#{optstr}: invalid context value.") + name, value = $1, $2 + name = name.gsub(/-/, '_').intern + #value = value.nil? ? true : YAML.load(value) # error, why? + value = value.nil? ? true : YAML.load("---\n#{value}\n") + context[name] = value + # + else # options + while optstr && !optstr.empty? + optchar = optstr[0].chr + optstr = optstr[1..-1] + if arg_none.include?(optchar) + options[optchar] = true + elsif arg_required.include?(optchar) + arg = optstr.empty? ? argv.shift : optstr or + raise CommandOptionError.new("-#{optchar}: #{@option_names[optchar]} required.") + options[optchar] = arg + optstr = nil + elsif arg_optional.include?(optchar) + arg = optstr.empty? ? true : optstr + options[optchar] = arg + optstr = nil + else + raise CommandOptionError.new("-#{optchar}: unknown option.") + end + end + end + # + end # end of while + + return options, context + end + + + def untabify(str, width=8) + list = str.split(/\t/) + last = list.pop + sb = '' + list.each do |s| + column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length + n = width - (column % width) + sb << s << (' ' * n) + end + sb << last + return sb + end + #-- + #def untabify(str, width=8) + # sb = '' + # str.scan(/(.*?)\t/m) do |s, | + # len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length + # sb << s << (" " * (width - len % width)) + # end + # return $' ? (sb << $') : str + #end + #++ + + + def get_classobj(classname, lang, pi) + classname ||= "E#{lang}" + base_module = pi ? Erubis::PI : Erubis + begin + klass = base_module.const_get(classname) + rescue NameError + klass = nil + end + unless klass + if lang + msg = "-l #{lang}: invalid language name (class #{base_module.name}::#{classname} not found)." + else + msg = "-c #{classname}: invalid class name." + end + raise CommandOptionError.new(msg) + end + return klass + end + + def get_enhancers(enhancer_names) + return [] unless enhancer_names + enhancers = [] + shortname = nil + begin + enhancer_names.split(/,/).each do |name| + shortname = name + enhancers << Erubis.const_get("#{shortname}Enhancer") + end + rescue NameError + raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-h' to show all enhancers).") + end + return enhancers + end + + def load_datafiles(filenames, opts) + context = Erubis::Context.new + return context unless filenames + filenames.split(/,/).each do |filename| + filename.strip! + test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.") + if filename =~ /\.ya?ml$/ + if opts.unexpand + ydoc = YAML.load_file(filename) + else + ydoc = YAML.load(untabify(File.read(filename))) + end + ydoc.is_a?(Hash) or raise CommandOptionError.new("#{filename}: root object is not a mapping.") + intern_hash_keys(ydoc) if opts.intern + context.update(ydoc) + elsif filename =~ /\.rb$/ + str = File.read(filename) + context2 = Erubis::Context.new + _instance_eval(context2, str) + context.update(context2) + else + CommandOptionError.new("#{filename}: '*.yaml', '*.yml', or '*.rb' required.") + end + end + return context + end + + def _instance_eval(_context, _str) + _context.instance_eval(_str) + end + + def parse_context_data(context_str, opts) + if context_str[0] == ?{ + require 'yaml' + ydoc = YAML.load(context_str) + unless ydoc.is_a?(Hash) + raise CommandOptionError.new("-c: root object is not a mapping.") + end + intern_hash_keys(ydoc) if opts.intern + return ydoc + else + context = Erubis::Context.new + context.instance_eval(context_str, '-c') + return context + end + end + + def intern_hash_keys(obj, done={}) + return if done.key?(obj.__id__) + case obj + when Hash + done[obj.__id__] = obj + obj.keys.each do |key| + obj[key.intern] = obj.delete(key) if key.is_a?(String) + end + obj.values.each do |val| + intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array) + end + when Array + done[obj.__id__] = obj + obj.each do |val| + intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array) + end + end + end + + def check_syntax(filename, src) + require 'open3' + #command = (ENV['_'] || 'ruby') + ' -wc' # ENV['_'] stores command name + bin = ENV['_'] && File.basename(ENV['_']) =~ /^ruby/ ? ENV['_'] : 'ruby' + command = bin + ' -wc' + stdin, stdout, stderr = Open3.popen3(command) + stdin.write(src) + stdin.close + result = stdout.read() + stdout.close() + errmsg = stderr.read() + stderr.close() + return nil unless errmsg && !errmsg.empty? + errmsg =~ /\A-:(\d+): / + linenum, message = $1, $' + return "#{filename}:#{linenum}: #{message}" + end + + if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx" + def check_syntax(filename, src) + require 'compiler' + verbose = $VERBOSE + msg = nil + begin + $VERBOSE = true + Rubinius::Compiler.compile_string(src, filename) + rescue SyntaxError => ex + ex_linenum = ex.line + linenum = 0 + srcline = src.each_line do |line| + linenum += 1 + break line if linenum == ex_linenum + end + msg = "#{ex.message}\n" + msg << srcline + msg << "\n" unless srcline =~ /\n\z/ + msg << (" " * (ex.column-1)) << "^\n" + ensure + $VERBOSE = verbose + end + return msg + end + end + + end + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/preprocessing.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/preprocessing.rb new file mode 100644 index 0000000..c2ceb96 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/preprocessing.rb @@ -0,0 +1,58 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'cgi' + + +module Erubis + + + ## + ## for preprocessing + ## + class PreprocessingEruby < Erubis::Eruby + + def initialize(input, params={}) + params = params.dup + params[:pattern] ||= '\[% %\]' # use '[%= %]' instead of '<%= %>' + #params[:escape] = true # transport '[%= %]' and '[%== %]' + super + end + + def add_expr_escaped(src, code) + add_expr_literal(src, "_decode((#{code}))") + end + + end + + + ## + ## helper methods for preprocessing + ## + module PreprocessingHelper + + module_function + + def _p(arg) + return "<%=#{arg}%>" + end + + def _P(arg) + return "<%=h(#{arg})%>" + end + + alias _? _p + + def _decode(arg) + arg = arg.to_s + arg.gsub!(/%3C%25(?:=|%3D)(.*?)%25%3E/) { "<%=#{CGI.unescape($1)}%>" } + arg.gsub!(/<%=(.*?)%>/) { "<%=#{CGI.unescapeHTML($1)}%>" } + return arg + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/tiny.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/tiny.rb new file mode 100644 index 0000000..05360ee --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/tiny.rb @@ -0,0 +1,144 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +module Erubis + + ## + ## tiny and the simplest implementation of eRuby + ## + ## ex. + ## eruby = TinyEruby.new(File.read('example.rhtml')) + ## print eruby.src # print ruby code + ## print eruby.result(binding()) # eval ruby code with Binding object + ## print eruby.evalute(context) # eval ruby code with context object + ## + class TinyEruby + + def initialize(input=nil) + @src = convert(input) if input + end + attr_reader :src + + EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m + + def convert(input) + src = "_buf = '';" # preamble + pos = 0 + input.scan(EMBEDDED_PATTERN) do |indicator, code| + m = Regexp.last_match + text = input[pos...m.begin(0)] + pos = m.end(0) + #src << " _buf << '" << escape_text(text) << "';" + text.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << text << "';" unless text.empty? + if !indicator # <% %> + src << code << ";" + elsif indicator == '#' # <%# %> + src << ("\n" * code.count("\n")) + else # <%= %> + src << " _buf << (" << code << ").to_s;" + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + #src << " _buf << '" << escape_text(rest) << "';" + rest.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << rest << "';" unless rest.empty? + src << "\n_buf.to_s\n" # postamble + return src + end + + #def escape_text(text) + # return text.gsub!(/['\\]/, '\\\\\&') || text + #end + + def result(_binding=TOPLEVEL_BINDING) + eval @src, _binding + end + + def evaluate(_context=Object.new) + if _context.is_a?(Hash) + _obj = Object.new + _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end + _context = _obj + end + _context.instance_eval @src + end + + end + + + + module PI + end + + class PI::TinyEruby + + def initialize(input=nil, options={}) + @escape = options[:escape] || 'Erubis::XmlHelper.escape_xml' + @src = convert(input) if input + end + + attr_reader :src + + EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m + + def convert(input) + src = "_buf = '';" # preamble + pos = 0 + input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr| + match = Regexp.last_match + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + #src << " _buf << '" << escape_text(text) << "';" + text.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << text << "';" unless text.empty? + if stmt # + if lspace && rspace + src << "#{lspace}#{stmt}#{rspace}" + else + src << " _buf << '" << lspace << "';" if lspace + src << stmt << ";" + src << " _buf << '" << rspace << "';" if rspace + end + else # ${...}, $!{...} + if !indicator + src << " _buf << " << @escape << "(" << expr << ");" + elsif indicator == '!' + src << " _buf << (" << expr << ").to_s;" + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + #src << " _buf << '" << escape_text(rest) << "';" + rest.gsub!(/['\\]/, '\\\\\&') + src << " _buf << '" << rest << "';" unless rest.empty? + src << "\n_buf.to_s\n" # postamble + return src + end + + #def escape_text(text) + # return text.gsub!(/['\\]/, '\\\\\&') || text + #end + + def result(_binding=TOPLEVEL_BINDING) + eval @src, _binding + end + + def evaluate(_context=Object.new) + if _context.is_a?(Hash) + _obj = Object.new + _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end + _context = _obj + end + _context.instance_eval @src + end + + end + + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/util.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/util.rb new file mode 100644 index 0000000..0d02fbb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/lib/erubis/util.rb @@ -0,0 +1,22 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +module Kernel + + ## + ## raise NotImplementedError + ## + def not_implemented #:doc: + backtrace = caller() + method_name = (backtrace.shift =~ /`(\w+)'$/) && $1 + mesg = "class #{self.class.name} must implement abstract method '#{method_name}()'." + #mesg = "#{self.class.name}##{method_name}() is not implemented." + err = NotImplementedError.new mesg + err.set_backtrace backtrace + raise err + end + private :not_implemented + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/setup.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/setup.rb new file mode 100644 index 0000000..f1c9d9a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/setup.rb @@ -0,0 +1,1331 @@ +# +# setup.rb +# +# Copyright (c) 2000-2004 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU Lesser General Public License version 2.1. +# + +# +# For backward compatibility +# + +unless Enumerable.method_defined?(:map) + module Enumerable + alias map collect + end +end + +unless Enumerable.method_defined?(:detect) + module Enumerable + alias detect find + end +end + +unless Enumerable.method_defined?(:select) + module Enumerable + alias select find_all + end +end + +unless Enumerable.method_defined?(:reject) + module Enumerable + def reject + result = [] + each do |i| + result.push i unless yield(i) + end + result + end + end +end + +unless Enumerable.method_defined?(:inject) + module Enumerable + def inject(result) + each do |i| + result = yield(result, i) + end + result + end + end +end + +unless Enumerable.method_defined?(:any?) + module Enumerable + def any? + each do |i| + return true if yield(i) + end + false + end + end +end + +unless File.respond_to?(:read) + def File.read(fname) + open(fname) {|f| + return f.read + } + end +end + +# +# Application independent utilities +# + +def File.binread(fname) + open(fname, 'rb') {|f| + return f.read + } +end + +# for corrupted windows stat(2) +def File.dir?(path) + File.directory?((path[-1,1] == '/') ? path : path + '/') +end + +# +# Config +# + +if arg = ARGV.detect{|arg| /\A--rbconfig=/ =~ arg } + ARGV.delete(arg) + require arg.split(/=/, 2)[1] + $".push 'rbconfig.rb' +else + require 'rbconfig' +end + +def multipackage_install? + FileTest.directory?(File.dirname($0) + '/packages') +end + + +class ConfigTable + + c = ::Config::CONFIG + + rubypath = c['bindir'] + '/' + c['ruby_install_name'] + + major = c['MAJOR'].to_i + minor = c['MINOR'].to_i + teeny = c['TEENY'].to_i + version = "#{major}.#{minor}" + + # ruby ver. >= 1.4.4? + newpath_p = ((major >= 2) or + ((major == 1) and + ((minor >= 5) or + ((minor == 4) and (teeny >= 4))))) + + subprefix = lambda {|path| + path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix') + } + + if c['rubylibdir'] + # V < 1.6.3 + stdruby = subprefix.call(c['rubylibdir']) + siteruby = subprefix.call(c['sitedir']) + versite = subprefix.call(c['sitelibdir']) + sodir = subprefix.call(c['sitearchdir']) + elsif newpath_p + # 1.4.4 <= V <= 1.6.3 + stdruby = "$prefix/lib/ruby/#{version}" + siteruby = subprefix.call(c['sitedir']) + versite = siteruby + '/' + version + sodir = "$site-ruby/#{c['arch']}" + else + # V < 1.4.4 + stdruby = "$prefix/lib/ruby/#{version}" + siteruby = "$prefix/lib/ruby/#{version}/site_ruby" + versite = siteruby + sodir = "$site-ruby/#{c['arch']}" + end + + if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } + makeprog = arg.sub(/'/, '').split(/=/, 2)[1] + else + makeprog = 'make' + end + + common_descripters = [ + [ 'prefix', [ c['prefix'], + 'path', + 'path prefix of target environment' ] ], + [ 'std-ruby', [ stdruby, + 'path', + 'the directory for standard ruby libraries' ] ], + [ 'site-ruby-common', [ siteruby, + 'path', + 'the directory for version-independent non-standard ruby libraries' ] ], + [ 'site-ruby', [ versite, + 'path', + 'the directory for non-standard ruby libraries' ] ], + [ 'bin-dir', [ '$prefix/bin', + 'path', + 'the directory for commands' ] ], + [ 'rb-dir', [ '$site-ruby', + 'path', + 'the directory for ruby scripts' ] ], + [ 'so-dir', [ sodir, + 'path', + 'the directory for ruby extentions' ] ], + [ 'data-dir', [ '$prefix/share', + 'path', + 'the directory for shared data' ] ], + [ 'ruby-path', [ rubypath, + 'path', + 'path to set to #! line' ] ], + [ 'ruby-prog', [ rubypath, + 'name', + 'the ruby program using for installation' ] ], + [ 'make-prog', [ makeprog, + 'name', + 'the make program to compile ruby extentions' ] ], + [ 'without-ext', [ 'no', + 'yes/no', + 'does not compile/install ruby extentions' ] ] + ] + multipackage_descripters = [ + [ 'with', [ '', + 'name,name...', + 'package names that you want to install', + 'ALL' ] ], + [ 'without', [ '', + 'name,name...', + 'package names that you do not want to install', + 'NONE' ] ] + ] + if multipackage_install? + DESCRIPTER = common_descripters + multipackage_descripters + else + DESCRIPTER = common_descripters + end + + SAVE_FILE = 'config.save' + + def ConfigTable.each_name(&block) + keys().each(&block) + end + + def ConfigTable.keys + DESCRIPTER.map {|name, *dummy| name } + end + + def ConfigTable.each_definition(&block) + DESCRIPTER.each(&block) + end + + def ConfigTable.get_entry(name) + name, ent = DESCRIPTER.assoc(name) + ent + end + + def ConfigTable.get_entry!(name) + get_entry(name) or raise ArgumentError, "no such config: #{name}" + end + + def ConfigTable.add_entry(name, vals) + ConfigTable::DESCRIPTER.push [name,vals] + end + + def ConfigTable.remove_entry(name) + get_entry(name) or raise ArgumentError, "no such config: #{name}" + DESCRIPTER.delete_if {|n, arr| n == name } + end + + def ConfigTable.config_key?(name) + get_entry(name) ? true : false + end + + def ConfigTable.bool_config?(name) + ent = get_entry(name) or return false + ent[1] == 'yes/no' + end + + def ConfigTable.value_config?(name) + ent = get_entry(name) or return false + ent[1] != 'yes/no' + end + + def ConfigTable.path_config?(name) + ent = get_entry(name) or return false + ent[1] == 'path' + end + + + class << self + alias newobj new + end + + def ConfigTable.new + c = newobj() + c.initialize_from_table + c + end + + def ConfigTable.load + c = newobj() + c.initialize_from_file + c + end + + def initialize_from_table + @table = {} + DESCRIPTER.each do |k, (default, vname, desc, default2)| + @table[k] = default + end + end + + def initialize_from_file + raise InstallError, "#{File.basename $0} config first"\ + unless File.file?(SAVE_FILE) + @table = {} + File.foreach(SAVE_FILE) do |line| + k, v = line.split(/=/, 2) + @table[k] = v.strip + end + end + + def save + File.open(SAVE_FILE, 'w') {|f| + @table.each do |k, v| + f.printf "%s=%s\n", k, v if v + end + } + end + + def []=(k, v) + raise InstallError, "unknown config option #{k}"\ + unless ConfigTable.config_key?(k) + @table[k] = v + end + + def [](key) + return nil unless @table[key] + @table[key].gsub(%r<\$([^/]+)>) { self[$1] } + end + + def set_raw(key, val) + @table[key] = val + end + + def get_raw(key) + @table[key] + end + +end + + +module MetaConfigAPI + + def eval_file_ifexist(fname) + instance_eval File.read(fname), fname, 1 if File.file?(fname) + end + + def config_names + ConfigTable.keys + end + + def config?(name) + ConfigTable.config_key?(name) + end + + def bool_config?(name) + ConfigTable.bool_config?(name) + end + + def value_config?(name) + ConfigTable.value_config?(name) + end + + def path_config?(name) + ConfigTable.path_config?(name) + end + + def add_config(name, argname, default, desc) + ConfigTable.add_entry name,[default,argname,desc] + end + + def add_path_config(name, default, desc) + add_config name, 'path', default, desc + end + + def add_bool_config(name, default, desc) + add_config name, 'yes/no', default ? 'yes' : 'no', desc + end + + def set_config_default(name, default) + if bool_config?(name) + ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no') + else + ConfigTable.get_entry!(name)[0] = default + end + end + + def remove_config(name) + ent = ConfigTable.get_entry(name) + ConfigTable.remove_entry name + ent + end + +end + +# +# File Operations +# + +module FileOperations + + def mkdir_p(dirname, prefix = nil) + dirname = prefix + dirname if prefix + $stderr.puts "mkdir -p #{dirname}" if verbose? + return if no_harm? + + # does not check '/'... it's too abnormal case + dirs = dirname.split(%r<(?=/)>) + if /\A[a-z]:\z/i =~ dirs[0] + disk = dirs.shift + dirs[0] = disk + dirs[0] + end + dirs.each_index do |idx| + path = dirs[0..idx].join('') + Dir.mkdir path unless File.dir?(path) + end + end + + def rm_f(fname) + $stderr.puts "rm -f #{fname}" if verbose? + return if no_harm? + + if File.exist?(fname) or File.symlink?(fname) + File.chmod 0777, fname + File.unlink fname + end + end + + def rm_rf(dn) + $stderr.puts "rm -rf #{dn}" if verbose? + return if no_harm? + + Dir.chdir dn + Dir.foreach('.') do |fn| + next if fn == '.' + next if fn == '..' + if File.dir?(fn) + verbose_off { + rm_rf fn + } + else + verbose_off { + rm_f fn + } + end + end + Dir.chdir '..' + Dir.rmdir dn + end + + def move_file(src, dest) + File.unlink dest if File.exist?(dest) + begin + File.rename src, dest + rescue + File.open(dest, 'wb') {|f| f.write File.binread(src) } + File.chmod File.stat(src).mode, dest + File.unlink src + end + end + + def install(from, dest, mode, prefix = nil) + $stderr.puts "install #{from} #{dest}" if verbose? + return if no_harm? + + realdest = prefix + dest if prefix + realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) + str = File.binread(from) + if diff?(str, realdest) + verbose_off { + rm_f realdest if File.exist?(realdest) + } + File.open(realdest, 'wb') {|f| + f.write str + } + File.chmod mode, realdest + + File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| + if prefix + f.puts realdest.sub(prefix, '') + else + f.puts realdest + end + } + end + end + + def diff?(new_content, path) + return true unless File.exist?(path) + new_content != File.binread(path) + end + + def command(str) + $stderr.puts str if verbose? + system str or raise RuntimeError, "'system #{str}' failed" + end + + def ruby(str) + command config('ruby-prog') + ' ' + str + end + + def make(task = '') + command config('make-prog') + ' ' + task + end + + def extdir?(dir) + File.exist?(dir + '/MANIFEST') + end + + def all_files_in(dirname) + Dir.open(dirname) {|d| + return d.select {|ent| File.file?("#{dirname}/#{ent}") } + } + end + + REJECT_DIRS = %w( + CVS SCCS RCS CVS.adm + ) + + def all_dirs_in(dirname) + Dir.open(dirname) {|d| + return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS + } + end + +end + +# +# Main Installer +# + +class InstallError < StandardError; end + + +module HookUtils + + def run_hook(name) + try_run_hook "#{curr_srcdir()}/#{name}" or + try_run_hook "#{curr_srcdir()}/#{name}.rb" + end + + def try_run_hook(fname) + return false unless File.file?(fname) + begin + instance_eval File.read(fname), fname, 1 + rescue + raise InstallError, "hook #{fname} failed:\n" + $!.message + end + true + end + +end + + +module HookScriptAPI + + def get_config(key) + @config[key] + end + + alias config get_config + + def set_config(key, val) + @config[key] = val + end + + # + # srcdir/objdir (works only in the package directory) + # + + #abstract srcdir_root + #abstract objdir_root + #abstract relpath + + def curr_srcdir + "#{srcdir_root()}/#{relpath()}" + end + + def curr_objdir + "#{objdir_root()}/#{relpath()}" + end + + def srcfile(path) + "#{curr_srcdir()}/#{path}" + end + + def srcexist?(path) + File.exist?(srcfile(path)) + end + + def srcdirectory?(path) + File.dir?(srcfile(path)) + end + + def srcfile?(path) + File.file? srcfile(path) + end + + def srcentries(path = '.') + Dir.open("#{curr_srcdir()}/#{path}") {|d| + return d.to_a - %w(. ..) + } + end + + def srcfiles(path = '.') + srcentries(path).select {|fname| + File.file?(File.join(curr_srcdir(), path, fname)) + } + end + + def srcdirectories(path = '.') + srcentries(path).select {|fname| + File.dir?(File.join(curr_srcdir(), path, fname)) + } + end + +end + + +class ToplevelInstaller + + Version = '3.2.4' + Copyright = 'Copyright (c) 2000-2004 Minero Aoki' + + TASKS = [ + [ 'config', 'saves your configurations' ], + [ 'show', 'shows current configuration' ], + [ 'setup', 'compiles ruby extentions and others' ], + [ 'install', 'installs files' ], + [ 'clean', "does `make clean' for each extention" ], + [ 'distclean',"does `make distclean' for each extention" ] + ] + + def ToplevelInstaller.invoke + instance().invoke + end + + @singleton = nil + + def ToplevelInstaller.instance + @singleton ||= new(File.dirname($0)) + @singleton + end + + include MetaConfigAPI + + def initialize(ardir_root) + @config = nil + @options = { 'verbose' => true } + @ardir = File.expand_path(ardir_root) + end + + def inspect + "#<#{self.class} #{__id__()}>" + end + + def invoke + run_metaconfigs + task = parsearg_global() + @config = load_config(task) + __send__ "parsearg_#{task}" + init_installers + __send__ "exec_#{task}" + end + + def run_metaconfigs + eval_file_ifexist "#{@ardir}/metaconfig" + end + + def load_config(task) + case task + when 'config' + ConfigTable.new + when 'clean', 'distclean' + if File.exist?('config.save') + then ConfigTable.load + else ConfigTable.new + end + else + ConfigTable.load + end + end + + def init_installers + @installer = Installer.new(@config, @options, @ardir, File.expand_path('.')) + end + + # + # Hook Script API bases + # + + def srcdir_root + @ardir + end + + def objdir_root + '.' + end + + def relpath + '.' + end + + # + # Option Parsing + # + + def parsearg_global + valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/ + + while arg = ARGV.shift + case arg + when /\A\w+\z/ + raise InstallError, "invalid task: #{arg}" unless valid_task =~ arg + return arg + + when '-q', '--quiet' + @options['verbose'] = false + + when '--verbose' + @options['verbose'] = true + + when '-h', '--help' + print_usage $stdout + exit 0 + + when '-v', '--version' + puts "#{File.basename($0)} version #{Version}" + exit 0 + + when '--copyright' + puts Copyright + exit 0 + + else + raise InstallError, "unknown global option '#{arg}'" + end + end + + raise InstallError, <" + out.puts " ruby #{File.basename $0} [] []" + + fmt = " %-20s %s\n" + out.puts + out.puts 'Global options:' + out.printf fmt, '-q,--quiet', 'suppress message outputs' + out.printf fmt, ' --verbose', 'output messages verbosely' + out.printf fmt, '-h,--help', 'print this message' + out.printf fmt, '-v,--version', 'print version and quit' + out.printf fmt, ' --copyright', 'print copyright and quit' + + out.puts + out.puts 'Tasks:' + TASKS.each do |name, desc| + out.printf " %-10s %s\n", name, desc + end + + out.puts + out.puts 'Options for config:' + ConfigTable.each_definition do |name, (default, arg, desc, default2)| + out.printf " %-20s %s [%s]\n", + '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg), + desc, + default2 || default + end + out.printf " %-20s %s [%s]\n", + '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's" + + out.puts + out.puts 'Options for install:' + out.printf " %-20s %s [%s]\n", + '--no-harm', 'only display what to do if given', 'off' + out.printf " %-20s %s [%s]\n", + '--prefix', 'install path prefix', '$prefix' + + out.puts + end + + # + # Task Handlers + # + + def exec_config + @installer.exec_config + @config.save # must be final + end + + def exec_setup + @installer.exec_setup + end + + def exec_install + @installer.exec_install + end + + def exec_show + ConfigTable.each_name do |k| + v = @config.get_raw(k) + if not v or v.empty? + v = '(not specified)' + end + printf "%-10s %s\n", k, v + end + end + + def exec_clean + @installer.exec_clean + end + + def exec_distclean + @installer.exec_distclean + end + +end + + +class ToplevelInstallerMulti < ToplevelInstaller + + include HookUtils + include HookScriptAPI + include FileOperations + + def initialize(ardir) + super + @packages = all_dirs_in("#{@ardir}/packages") + raise 'no package exists' if @packages.empty? + end + + def run_metaconfigs + eval_file_ifexist "#{@ardir}/metaconfig" + @packages.each do |name| + eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig" + end + end + + def init_installers + @installers = {} + @packages.each do |pack| + @installers[pack] = Installer.new(@config, @options, + "#{@ardir}/packages/#{pack}", + "packages/#{pack}") + end + + with = extract_selection(config('with')) + without = extract_selection(config('without')) + @selected = @installers.keys.select {|name| + (with.empty? or with.include?(name)) \ + and not without.include?(name) + } + end + + def extract_selection(list) + a = list.split(/,/) + a.each do |name| + raise InstallError, "no such package: #{name}" \ + unless @installers.key?(name) + end + a + end + + def print_usage(f) + super + f.puts 'Inluded packages:' + f.puts ' ' + @packages.sort.join(' ') + f.puts + end + + # + # multi-package metaconfig API + # + + attr_reader :packages + + def declare_packages(list) + raise 'package list is empty' if list.empty? + list.each do |name| + raise "directory packages/#{name} does not exist"\ + unless File.dir?("#{@ardir}/packages/#{name}") + end + @packages = list + end + + # + # Task Handlers + # + + def exec_config + run_hook 'pre-config' + each_selected_installers {|inst| inst.exec_config } + run_hook 'post-config' + @config.save # must be final + end + + def exec_setup + run_hook 'pre-setup' + each_selected_installers {|inst| inst.exec_setup } + run_hook 'post-setup' + end + + def exec_install + run_hook 'pre-install' + each_selected_installers {|inst| inst.exec_install } + run_hook 'post-install' + end + + def exec_clean + rm_f 'config.save' + run_hook 'pre-clean' + each_selected_installers {|inst| inst.exec_clean } + run_hook 'post-clean' + end + + def exec_distclean + rm_f 'config.save' + run_hook 'pre-distclean' + each_selected_installers {|inst| inst.exec_distclean } + run_hook 'post-distclean' + end + + # + # lib + # + + def each_selected_installers + Dir.mkdir 'packages' unless File.dir?('packages') + @selected.each do |pack| + $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose'] + Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") + Dir.chdir "packages/#{pack}" + yield @installers[pack] + Dir.chdir '../..' + end + end + + def verbose? + @options['verbose'] + end + + def no_harm? + @options['no-harm'] + end + +end + + +class Installer + + FILETYPES = %w( bin lib ext data ) + + include HookScriptAPI + include HookUtils + include FileOperations + + def initialize(config, opt, srcroot, objroot) + @config = config + @options = opt + @srcdir = File.expand_path(srcroot) + @objdir = File.expand_path(objroot) + @currdir = '.' + end + + def inspect + "#<#{self.class} #{File.basename(@srcdir)}>" + end + + # + # Hook Script API bases + # + + def srcdir_root + @srcdir + end + + def objdir_root + @objdir + end + + def relpath + @currdir + end + + # + # configs/options + # + + def no_harm? + @options['no-harm'] + end + + def verbose? + @options['verbose'] + end + + def verbose_off + begin + save, @options['verbose'] = @options['verbose'], false + yield + ensure + @options['verbose'] = save + end + end + + # + # TASK config + # + + def exec_config + exec_task_traverse 'config' + end + + def config_dir_bin(rel) + end + + def config_dir_lib(rel) + end + + def config_dir_ext(rel) + extconf if extdir?(curr_srcdir()) + end + + def extconf + opt = @options['config-opt'].join(' ') + command "#{config('ruby-prog')} #{curr_srcdir()}/extconf.rb #{opt}" + end + + def config_dir_data(rel) + end + + # + # TASK setup + # + + def exec_setup + exec_task_traverse 'setup' + end + + def setup_dir_bin(rel) + all_files_in(curr_srcdir()).each do |fname| + adjust_shebang "#{curr_srcdir()}/#{fname}" + end + end + + # modify: #!/usr/bin/ruby + # modify: #! /usr/bin/ruby + # modify: #!ruby + # not modify: #!/usr/bin/env ruby + SHEBANG_RE = /\A\#!\s*\S*ruby\S*/ + + def adjust_shebang(path) + return if no_harm? + + tmpfile = File.basename(path) + '.tmp' + begin + File.open(path, 'rb') {|r| + File.open(tmpfile, 'wb') {|w| + first = r.gets + return unless SHEBANG_RE =~ first + + $stderr.puts "adjusting shebang: #{File.basename path}" if verbose? + w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path')) + w.write r.read + } + } + move_file tmpfile, File.basename(path) + ensure + File.unlink tmpfile if File.exist?(tmpfile) + end + end + + def setup_dir_lib(rel) + end + + def setup_dir_ext(rel) + make if extdir?(curr_srcdir()) + end + + def setup_dir_data(rel) + end + + # + # TASK install + # + + def exec_install + exec_task_traverse 'install' + end + + def install_dir_bin(rel) + install_files collect_filenames_auto(), "#{config('bin-dir')}/#{rel}", 0755 + end + + def install_dir_lib(rel) + install_files ruby_scripts(), "#{config('rb-dir')}/#{rel}", 0644 + end + + def install_dir_ext(rel) + return unless extdir?(curr_srcdir()) + install_files ruby_extentions('.'), + "#{config('so-dir')}/#{File.dirname(rel)}", + 0555 + end + + def install_dir_data(rel) + install_files collect_filenames_auto(), "#{config('data-dir')}/#{rel}", 0644 + end + + def install_files(list, dest, mode) + mkdir_p dest, @options['install-prefix'] + list.each do |fname| + install fname, dest, mode, @options['install-prefix'] + end + end + + def ruby_scripts + collect_filenames_auto().select {|n| /\.rb\z/ =~ n } + end + + # picked up many entries from cvs-1.11.1/src/ignore.c + reject_patterns = %w( + core RCSLOG tags TAGS .make.state + .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb + *~ *.old *.bak *.BAK *.orig *.rej _$* *$ + + *.org *.in .* + ) + mapping = { + '.' => '\.', + '$' => '\$', + '#' => '\#', + '*' => '.*' + } + REJECT_PATTERNS = Regexp.new('\A(?:' + + reject_patterns.map {|pat| + pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] } + }.join('|') + + ')\z') + + def collect_filenames_auto + mapdir((existfiles() - hookfiles()).reject {|fname| + REJECT_PATTERNS =~ fname + }) + end + + def existfiles + all_files_in(curr_srcdir()) | all_files_in('.') + end + + def hookfiles + %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| + %w( config setup install clean ).map {|t| sprintf(fmt, t) } + }.flatten + end + + def mapdir(filelist) + filelist.map {|fname| + if File.exist?(fname) # objdir + fname + else # srcdir + File.join(curr_srcdir(), fname) + end + } + end + + def ruby_extentions(dir) + _ruby_extentions(dir) or + raise InstallError, "no ruby extention exists: 'ruby #{$0} setup' first" + end + + DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/ + + def _ruby_extentions(dir) + Dir.open(dir) {|d| + return d.select {|fname| DLEXT =~ fname } + } + end + + # + # TASK clean + # + + def exec_clean + exec_task_traverse 'clean' + rm_f 'config.save' + rm_f 'InstalledFiles' + end + + def clean_dir_bin(rel) + end + + def clean_dir_lib(rel) + end + + def clean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'clean' if File.file?('Makefile') + end + + def clean_dir_data(rel) + end + + # + # TASK distclean + # + + def exec_distclean + exec_task_traverse 'distclean' + rm_f 'config.save' + rm_f 'InstalledFiles' + end + + def distclean_dir_bin(rel) + end + + def distclean_dir_lib(rel) + end + + def distclean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'distclean' if File.file?('Makefile') + end + + # + # lib + # + + def exec_task_traverse(task) + run_hook "pre-#{task}" + FILETYPES.each do |type| + if config('without-ext') == 'yes' and type == 'ext' + $stderr.puts 'skipping ext/* by user option' if verbose? + next + end + traverse task, type, "#{task}_dir_#{type}" + end + run_hook "post-#{task}" + end + + def traverse(task, rel, mid) + dive_into(rel) { + run_hook "pre-#{task}" + __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') + all_dirs_in(curr_srcdir()).each do |d| + traverse task, "#{rel}/#{d}", mid + end + run_hook "post-#{task}" + } + end + + def dive_into(rel) + return unless File.dir?("#{@srcdir}/#{rel}") + + dir = File.basename(rel) + Dir.mkdir dir unless File.dir?(dir) + prevdir = Dir.pwd + Dir.chdir dir + $stderr.puts '---> ' + rel if verbose? + @currdir = rel + yield + Dir.chdir prevdir + $stderr.puts '<--- ' + rel if verbose? + @currdir = File.dirname(rel) + end + +end + + +if $0 == __FILE__ + begin + if multipackage_install? + ToplevelInstallerMulti.invoke + else + ToplevelInstaller.invoke + end + rescue + raise if $DEBUG + $stderr.puts $!.message + $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." + exit 1 + end +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/assert-text-equal.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/assert-text-equal.rb new file mode 100644 index 0000000..9047578 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/assert-text-equal.rb @@ -0,0 +1,44 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'test/unit' +require 'tempfile' + + +module Test + module Unit + class TestCase + + def assert_text_equal(expected, actual, message=nil, diffopt='-u', flag_cut=true) + if expected == actual + assert(true) + return + end + if expected[-1] != ?\n || actual[-1] != ?\n + expected += "\n" + actual += "\n" + end + begin + expfile = Tempfile.new(".expected.") + expfile.write(expected); expfile.flush() + actfile = Tempfile.new(".actual.") + actfile.write(actual); actfile.flush() + diff = `diff #{diffopt} #{expfile.path} #{actfile.path}` + ensure + expfile.close(true) if expfile + actfile.close(true) if actfile + end + # cut 1st & 2nd lines + message = (flag_cut ? diff.gsub(/\A.*\n.*\n/, '') : diff) unless message + #raise Test::Unit::AssertionFailedError.new(message) + assert_block(message) { false } # or assert(false, message) + end + + alias assert_equal_with_diff assert_text_equal # for compatibility + alias assert_text_equals assert_text_equal # for typo + + end + end +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/Example.ejava b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/Example.ejava new file mode 100644 index 0000000..1fc2fe0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/Example.ejava @@ -0,0 +1,55 @@ +<% +import java.util.*; + +public class Example { + private String user; + private String[] list; + public example(String user, String[] list) { + this.user = user; + this.list = list; + } + + public String view() { + StringBuffer _buf = new StringBuffer(); +%> + + +

    Hello <%= user %>!

    + + + <% for (int i = 0; i < list.length; i++) { %> + "> + + + + <% } %> + +
    <%= i + 1 %><%== list[i] %>
    + + +<% + return _buf.toString(); + } + + public static void main(String[] args) { + String[] list = { "", "b&b", "\"ccc\"" }; + Example ex = Example.new("Erubis", list); + System.out.print(ex.view()); + } + + public static String escape(String s) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '<': sb.append("<"); break; + case '>': sb.append(">"); break; + case '&': sb.append("&"); break; + case '"': sb.append("""); break; + default: sb.append(ch); + } + } + return sb.toString(); + } +} +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/array_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/array_example.result new file mode 100644 index 0000000..ebd00f4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/array_example.result @@ -0,0 +1,9 @@ +$ erubis -xE Array example.eruby +_buf = []; _buf << '
    +'; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end + _buf << '
    +'; +_buf diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/arraybuffer_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/arraybuffer_example.result new file mode 100644 index 0000000..d2906db --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/arraybuffer_example.result @@ -0,0 +1,9 @@ +$ erubis -xE ArrayBuffer example.eruby +_buf = []; _buf << '
    +'; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end + _buf << '
    +'; +_buf.join diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bipattern-example.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bipattern-example.rhtml new file mode 100644 index 0000000..a47fda8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bipattern-example.rhtml @@ -0,0 +1,4 @@ +<% for item in list %> + [= item =] + [== item =] +<% end %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bipattern_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bipattern_example.result new file mode 100644 index 0000000..15159b5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bipattern_example.result @@ -0,0 +1,6 @@ +$ erubis -xE BiPattern bipattern-example.rhtml +_buf = ''; for item in list + _buf << ' '; _buf << ( item ).to_s; _buf << ' + '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << ' +'; end +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bufvar-example.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bufvar-example.rb new file mode 100644 index 0000000..928d13d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bufvar-example.rb @@ -0,0 +1,10 @@ +require 'erubis' +input = File.read('example.eruby') + +puts "----- default -----" +eruby = Erubis::FastEruby.new(input) +puts eruby.src + +puts "----- with :bufvar option -----" +eruby = Erubis::FastEruby.new(input, :bufvar=>'@_out_buf') +print eruby.src diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bufvar-example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bufvar-example.result new file mode 100644 index 0000000..47856fa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/bufvar-example.result @@ -0,0 +1,17 @@ +$ ruby bufvar-example.rb +----- default ----- +_buf = ''; _buf << %Q`
    \n` + for item in list + _buf << %Q`

    #{ item }

    +

    #{Erubis::XmlHelper.escape_xml( item )}

    \n` + end + _buf << %Q`
    \n` +_buf.to_s +----- with :bufvar option ----- +@_out_buf = ''; @_out_buf << %Q`
    \n` + for item in list + @_out_buf << %Q`

    #{ item }

    +

    #{Erubis::XmlHelper.escape_xml( item )}

    \n` + end + @_out_buf << %Q`
    \n` +@_out_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/context.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/context.rb new file mode 100644 index 0000000..66a6663 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/context.rb @@ -0,0 +1,6 @@ +@title = 'Users List' +@users = [ + { 'name'=>'foo', 'mail'=>'foo@mail.com' }, + { 'name'=>'bar', 'mail'=>'bar@mail.net' }, + { 'name'=>'baz', 'mail'=>'baz@mail.org' }, +] diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/context.yaml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/context.yaml new file mode 100644 index 0000000..25f4e19 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/context.yaml @@ -0,0 +1,8 @@ +title: Users List +users: + - name: foo + mail: foo@mail.com + - name: bar + mail: bar@mail.net + - name: baz + mail: baz@mail.org diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/def_method.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/def_method.rb new file mode 100644 index 0000000..3b378da --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/def_method.rb @@ -0,0 +1,14 @@ +require 'erubis' +s = "hello <%= name %>" +eruby = Erubis::Eruby.new(s) +filename = 'hello.rhtml' + +## define instance method to Dummy class (or module) +class Dummy; end +eruby.def_method(Dummy, 'render(name)', filename) # filename is optional +p Dummy.new.render('world') #=> "hello world" + +## define singleton method to dummy object +obj = Object.new +eruby.def_method(obj, 'render(name)', filename) # filename is optional +p obj.render('world') #=> "hello world" diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/def_method.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/def_method.result new file mode 100644 index 0000000..f2a1b5b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/def_method.result @@ -0,0 +1,3 @@ +$ ruby def_method.rb +"hello world" +"hello world" diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/escape_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/escape_example.result new file mode 100644 index 0000000..95de2dc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/escape_example.result @@ -0,0 +1,9 @@ +$ erubis -xE Escape example.eruby +_buf = ''; _buf << '
    +'; for item in list + _buf << '

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +

    '; _buf << ( item ).to_s; _buf << '

    +'; end + _buf << '
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ec b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ec new file mode 100644 index 0000000..a804f05 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ec @@ -0,0 +1,27 @@ +<% +#include + +int main(int argc, char *argv[]) +{ + int i; + +%> + + +

    Hello <%= "%s", argv[0] %>!

    + + + <% for (i = 1; i < argc; i++) { %> + "> + + + + <% } %> + +
    <%= "%d", i %><%= "%s", argv[i] %>
    + + +<% + return 0; +} +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ecpp b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ecpp new file mode 100644 index 0000000..f97c4e2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ecpp @@ -0,0 +1,30 @@ +<% +#include +#include +#include + +int main(int argc, char *argv[]) +{ + std::stringstream _buf; +%> + + +

    Hello <%= argv[0] %>!

    + + + <% for (int i = 1; i < argc; i++) { %> + "> + + + + <% } %> + +
    <%= i %><%= argv[i] %>
    + + +<% + std::string output = _buf.str(); + std::cout << output; + return 0; +} +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ejs b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ejs new file mode 100644 index 0000000..44f2e3f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ejs @@ -0,0 +1,20 @@ +<% + var user = 'Erubis'; + var list = ['', 'b&b', '"ccc"']; + %> + + +

    Hello <%= user %>!

    + + + <% var i; %> + <% for (i = 0; i < list.length; i++) { %> + + + + + <% } %> + +
    <%= i + 1 %><%= list[i] %>
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.eperl b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.eperl new file mode 100644 index 0000000..46f7508 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.eperl @@ -0,0 +1,18 @@ +<% + my $user = 'Erubis'; + my @list = ('', 'b&b', '"ccc"'); +%> + + +

    Hello <%= $user %>!

    + + <% $i = 0; %> + <% for $item (@list) { %> + "> + + + + <% } %> +
    <%= $i %><%= $item %>
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ephp b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ephp new file mode 100644 index 0000000..d92b46c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.ephp @@ -0,0 +1,18 @@ + + + +

    Hello <%= $user %>!

    + + + <% $i = 0; %> + <% foreach ($list as $item) { %> + <% $i++; %> + + + + + <% } %> + +
    <%= $i %><%== $item %>
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.eruby new file mode 100644 index 0000000..564c876 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.eruby @@ -0,0 +1,6 @@ +
    +<% for item in list %> +

    <%= item %>

    +

    <%== item %>

    +<% end %> +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.escheme b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.escheme new file mode 100644 index 0000000..e2296ba --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example.escheme @@ -0,0 +1,28 @@ + + +<% +(let ((user "Erubis") + (items '("" "b&b" "\"ccc\"")) + (i 0)) + %> +

    Hello <%= user %>!

    + +<% + (for-each + (lambda (item) + (set! i (+ i 1)) + %> + "> + + + +<% + ) ; lambda end + items) ; for-each end + %> +
    <%= i %><%= item %>
    +<% +) ; let end +%> + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.eruby new file mode 100644 index 0000000..84bd1fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.eruby @@ -0,0 +1,6 @@ +
      + <% for item in list %> +
    • <%= item %>
    • + <% end %> + <%# here is ignored because starting with '#' %> +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.rb new file mode 100644 index 0000000..8838206 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.rb @@ -0,0 +1,17 @@ +require 'erubis' +input = File.read('example1.eruby') +eruby = Erubis::Eruby.new(input) # create Eruby object + +puts "---------- script source ---" +puts eruby.src # print script source + +puts "---------- result ----------" +list = ['aaa', 'bbb', 'ccc'] +puts eruby.result(binding()) # get result +## or puts eruby.result(:list=>list) # or pass Hash instead of Binding + +## # or +## eruby = Erubis::Eruby.new +## input = File.read('example1.eruby') +## src = eruby.convert(input) +## eval src diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.result new file mode 100644 index 0000000..95ee6bb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1.result @@ -0,0 +1,16 @@ +$ ruby example1.rb +---------- script source --- +_buf = ''; _buf << '
      +'; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • +'; end + + _buf << '
    +'; +_buf.to_s +---------- result ---------- +
      +
    • aaa
    • +
    • bbb
    • +
    • ccc
    • +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.rb new file mode 100644 index 0000000..b459cc0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.rb @@ -0,0 +1,4 @@ +require 'erubis' +input = File.read('example10.xhtml') +eruby = Erubis::PI::Eruby.new(input) +print eruby.src diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.result new file mode 100644 index 0000000..b080fa8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.result @@ -0,0 +1,17 @@ +$ ruby example10.rb +_buf = ''; _buf << ' +'; + lang = 'en' + list = ['', 'b&b', '"ccc"'] + + _buf << ' + +
      +'; for item in list + _buf << '
    • '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '
    • +'; end + _buf << '
    + + +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.xhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.xhtml new file mode 100644 index 0000000..3ec00d5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10.xhtml @@ -0,0 +1,14 @@ + +', 'b&b', '"ccc"'] +?> + + +
      + +
    • @{item}@
    • + +
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10_x.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10_x.result new file mode 100644 index 0000000..d19e078 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example10_x.result @@ -0,0 +1,17 @@ +$ erubis -x --pi example10.xhtml +_buf = ''; _buf << ' +'; + lang = 'en' + list = ['', 'b&b', '"ccc"'] + + _buf << ' + +
      +'; for item in list + _buf << '
    • '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '
    • +'; end + _buf << '
    + + +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.php b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.php new file mode 100644 index 0000000..354ffc0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.php @@ -0,0 +1,20 @@ + + + +

    List

    + +

    not found.

    + + + + + + + + + + +
    + + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.result new file mode 100644 index 0000000..f69bb2d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.result @@ -0,0 +1,23 @@ +$ erubis -X example11.rhtml +_buf = ''; + + + + + + if @list.nil? || @list.empty? + + else + + + @list.each_with_index do |item, i| + _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s; + _buf << ( item ).to_s; + + end + + + end + + +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.rhtml new file mode 100644 index 0000000..93d9326 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11.rhtml @@ -0,0 +1,21 @@ + + + + +

    List

    + <% if @list.nil? || @list.empty? %> +

    not found.

    + <% else %> + + + <% @list.each_with_index do |item, i| %> + + + + <% end %> + +
    <%= item %>
    + <% end %> + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_C.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_C.result new file mode 100644 index 0000000..a394dae --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_C.result @@ -0,0 +1,10 @@ +$ erubis -XC example11.rhtml +_buf = ''; + if @list.nil? || @list.empty? + else + @list.each_with_index do |item, i| + _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s; + _buf << ( item ).to_s; + end + end +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_N.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_N.result new file mode 100644 index 0000000..ef0ad4a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_N.result @@ -0,0 +1,16 @@ +$ erubis -XNU example11.rhtml + 1: _buf = ''; + + 7: if @list.nil? || @list.empty? + + 9: else + + 12: @list.each_with_index do |item, i| + 13: _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s; + 14: _buf << ( item ).to_s; + + 16: end + + 19: end + + 22: _buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_U.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_U.result new file mode 100644 index 0000000..2c89bbb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_U.result @@ -0,0 +1,16 @@ +$ erubis -XU example11.rhtml +_buf = ''; + + if @list.nil? || @list.empty? + + else + + @list.each_with_index do |item, i| + _buf << ( i % 2 == 0 ? '#FCC' : '#CCF' ).to_s; + _buf << ( item ).to_s; + + end + + end + +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_php.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_php.result new file mode 100644 index 0000000..65f62dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example11_php.result @@ -0,0 +1,15 @@ +$ erubis -XNU -l php --pi=php --trim=false example11.php + + 5: + + 7: + + 10: + 11: + 12: + 13: + + 15: + + 18: + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1_x.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1_x.result new file mode 100644 index 0000000..ab305c5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example1_x.result @@ -0,0 +1,9 @@ +$ erubis -x example1.eruby +_buf = ''; _buf << '
      +'; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • +'; end + + _buf << '
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.eruby new file mode 100644 index 0000000..a9ef194 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.eruby @@ -0,0 +1,7 @@ +
      + <% for item in list %> +
    • + <%= item %> +
    • + <% end %> +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.rb new file mode 100644 index 0000000..29b969b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.rb @@ -0,0 +1,10 @@ +require 'erubis' +input = File.read('example2.eruby') +eruby = Erubis::Eruby.new(input, :trim=>false) + +puts "----- script source ---" +puts eruby.src # print script source + +puts "----- result ----------" +list = ['aaa', 'bbb', 'ccc'] +puts eruby.result(binding()) # get result diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.result new file mode 100644 index 0000000..0a5b2d5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2.result @@ -0,0 +1,27 @@ +$ ruby example2.rb +----- script source --- +_buf = ''; _buf << '
      +'; _buf << ' '; for item in list ; _buf << ' +'; _buf << '
    • + '; _buf << ( item ).to_s; _buf << ' +'; _buf << '
    • +'; _buf << ' '; end ; _buf << ' +'; _buf << '
    +'; +_buf.to_s +----- result ---------- +
      + +
    • + aaa +
    • + +
    • + bbb +
    • + +
    • + ccc +
    • + +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2_trim.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2_trim.result new file mode 100644 index 0000000..1f4e6f0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2_trim.result @@ -0,0 +1,10 @@ +$ erubis -x --trim=false example2.eruby +_buf = ''; _buf << '
      +'; _buf << ' '; for item in list ; _buf << ' +'; _buf << '
    • + '; _buf << ( item ).to_s; _buf << ' +'; _buf << '
    • +'; _buf << ' '; end ; _buf << ' +'; _buf << '
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2_x.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2_x.result new file mode 100644 index 0000000..81d0dcf --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example2_x.result @@ -0,0 +1,10 @@ +$ erubis -x example2.eruby +_buf = ''; _buf << '
      +'; for item in list + _buf << '
    • + '; _buf << ( item ).to_s; _buf << ' +'; _buf << '
    • +'; end + _buf << '
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3.eruby new file mode 100644 index 0000000..9bb5e35 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3.eruby @@ -0,0 +1,6 @@ +<% for item in list %> +

    <%= item %>

    +

    <%== item %>

    +

    <%=== item %>

    + +<% end %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3.rb new file mode 100644 index 0000000..482b511 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3.rb @@ -0,0 +1,10 @@ +require 'erubis' +input = File.read('example3.eruby') +eruby = Erubis::EscapedEruby.new(input) # or Erubis::XmlEruby + +puts "----- script source ---" +puts eruby.src # print script source + +puts "----- result ----------" +list = ['', 'b&b', '"ccc"'] +puts eruby.result(binding()) # get result diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example31.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example31.result new file mode 100644 index 0000000..9c37839 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example31.result @@ -0,0 +1,22 @@ +$ ruby example3.rb 2> stderr.log +----- script source --- +_buf = ''; for item in list + _buf << '

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +

    '; _buf << ( item ).to_s; _buf << '

    +

    '; $stderr.puts("*** debug: item=#{(item).inspect}"); _buf << '

    + +'; end +_buf.to_s +----- result ---------- +

    <aaa>

    +

    +

    + +

    b&b

    +

    b&b

    +

    + +

    "ccc"

    +

    "ccc"

    +

    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example32.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example32.result new file mode 100644 index 0000000..692524a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example32.result @@ -0,0 +1,4 @@ +$ cat stderr.log +*** debug: item="" +*** debug: item="b&b" +*** debug: item="\"ccc\"" diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3_e.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3_e.result new file mode 100644 index 0000000..b5b45c2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example3_e.result @@ -0,0 +1,8 @@ +$ erubis -l ruby -e example3.eruby +_buf = ''; for item in list + _buf << '

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +

    '; _buf << ( item ).to_s; _buf << '

    +

    '; $stderr.puts("*** debug: item=#{(item).inspect}"); _buf << '

    + +'; end +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.eruby new file mode 100644 index 0000000..3550f5a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.eruby @@ -0,0 +1,3 @@ + +

    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.rb new file mode 100644 index 0000000..e8d0d8d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.rb @@ -0,0 +1,11 @@ +require 'erubis' +input = File.read('example4.eruby') +eruby = Erubis::Eruby.new(input, :pattern=>'') + # or '<(?:!--)?% %(?:--)?>' + +puts "---------- script source ---" +puts eruby.src # print script source + +puts "---------- result ----------" +list = ['aaa', 'bbb', 'ccc'] +puts eruby.result(binding()) # get result diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.result new file mode 100644 index 0000000..bcd1e2a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4.result @@ -0,0 +1,10 @@ +$ ruby example4.rb +---------- script source --- +_buf = ''; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +'; end +_buf.to_s +---------- result ---------- +

    aaa

    +

    bbb

    +

    ccc

    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4_x.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4_x.result new file mode 100644 index 0000000..97edb2f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example4_x.result @@ -0,0 +1,5 @@ +$ erubis -x -p '' example4.eruby +_buf = ''; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +'; end +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.eruby new file mode 100644 index 0000000..e106fd9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.eruby @@ -0,0 +1,6 @@ +<%= @val %> +
      + <% for item in @list %> +
    • <%= item %>
    • + <% end %> +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.rb new file mode 100644 index 0000000..2ad042e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.rb @@ -0,0 +1,16 @@ +require 'erubis' +input = File.read('example5.eruby') +eruby = Erubis::Eruby.new(input) # create Eruby object + +## create context object +## (key means var name, which may be string or symbol.) +context = { + :val => 'Erubis Example', + 'list' => ['aaa', 'bbb', 'ccc'], +} +## or +# context = Erubis::Context.new() +# context['val'] = 'Erubis Example' +# context[:list] = ['aaa', 'bbb', 'ccc'], + +puts eruby.evaluate(context) # get result diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.result new file mode 100644 index 0000000..836f6ce --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example5.result @@ -0,0 +1,7 @@ +$ ruby example5.rb +Erubis Example +
      +
    • aaa
    • +
    • bbb
    • +
    • ccc
    • +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example6.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example6.rb new file mode 100644 index 0000000..f80719f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example6.rb @@ -0,0 +1,12 @@ +class MyData + attr_accessor :val, :list +end + +## any object can be a context object +mydata = MyData.new +mydata.val = 'Erubis Example' +mydata.list = ['aaa', 'bbb', 'ccc'] + +require 'erubis' +eruby = Erubis::Eruby.new(File.read('example5.eruby')) +puts eruby.evaluate(mydata) diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example6.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example6.result new file mode 100644 index 0000000..f482d0b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example6.result @@ -0,0 +1,7 @@ +$ ruby example6.rb +Erubis Example +
      +
    • aaa
    • +
    • bbb
    • +
    • ccc
    • +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example7.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example7.eruby new file mode 100644 index 0000000..53f9ec8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example7.eruby @@ -0,0 +1,8 @@ +

    <%= @title %>

    +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example71.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example71.result new file mode 100644 index 0000000..ab555b1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example71.result @@ -0,0 +1,13 @@ +$ erubis -f context.yaml example7.eruby +

    Users List

    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example72.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example72.result new file mode 100644 index 0000000..dfcafd3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example72.result @@ -0,0 +1,13 @@ +$ erubis -f context.rb example7.eruby +

    Users List

    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8.eruby new file mode 100644 index 0000000..5ea6da8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8.eruby @@ -0,0 +1,6 @@ +

    <%= @title %>

    +
      +<% for item in @list %> +
    • <%= item %>
    • +<% end %> +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8_ruby.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8_ruby.result new file mode 100644 index 0000000..bdfd23e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8_ruby.result @@ -0,0 +1,7 @@ +$ erubis -c '@title="Example"; @list=%w[AAA BBB CCC]' example8.eruby +

    Example

    +
      +
    • AAA
    • +
    • BBB
    • +
    • CCC
    • +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8_yaml.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8_yaml.result new file mode 100644 index 0000000..739e42b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example8_yaml.result @@ -0,0 +1,7 @@ +$ erubis -c '{title: Example, list: [AAA, BBB, CCC]}' example8.eruby +

    Example

    +
      +
    • AAA
    • +
    • BBB
    • +
    • CCC
    • +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.eruby new file mode 100644 index 0000000..0f2dc8f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.eruby @@ -0,0 +1,3 @@ +<% for item in @list %> + <%= item %> +<% end %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.rb new file mode 100644 index 0000000..bde1de6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.rb @@ -0,0 +1,8 @@ +require 'erubis' +input = File.read('example9.eruby') +eruby1 = Erubis::Eruby.new(input) +eruby2 = Erubis::Eruby.new(input, :preamble=>false, :postamble=>false) + +puts eruby1.src # print preamble and postamble +puts "--------------" +puts eruby2.src # don't print preamble and postamble diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.result new file mode 100644 index 0000000..60e71e2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example9.result @@ -0,0 +1,9 @@ +$ ruby example9.rb +_buf = ''; for item in @list + _buf << ' '; _buf << ( item ).to_s; _buf << ' +'; end +_buf.to_s +-------------- + for item in @list + _buf << ' '; _buf << ( item ).to_s; _buf << ' +'; end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example91.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example91.result new file mode 100644 index 0000000..fde06a8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example91.result @@ -0,0 +1,5 @@ +$ erubis -x example9.eruby +_buf = ''; for item in @list + _buf << ' '; _buf << ( item ).to_s; _buf << ' +'; end +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example92.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example92.result new file mode 100644 index 0000000..0cff68d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example92.result @@ -0,0 +1,4 @@ +$ erubis -x -b example9.eruby + for item in @list + _buf << ' '; _buf << ( item ).to_s; _buf << ' +'; end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_c.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_c.result new file mode 100644 index 0000000..9d36897 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_c.result @@ -0,0 +1,32 @@ +$ erubis -l cpp example.ecpp +#line 1 "example.ecpp" + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + std::stringstream _buf; + +_buf << "\n" + " \n" + "

    Hello "; _buf << (argv[0]); _buf << "!

    \n" + " \n" + " \n"; + for (int i = 1; i < argc; i++) { +_buf << " \n" + " \n" + " \n" + " \n"; + } +_buf << " \n" + "
    "; _buf << (i); _buf << ""; _buf << (argv[i]); _buf << "
    \n" + " \n" + "\n"; + + std::string output = _buf.str(); + std::cout << output; + return 0; +} + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_java.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_java.result new file mode 100644 index 0000000..70c10d2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_java.result @@ -0,0 +1,56 @@ +$ erubis -b -l java example.ejava + +import java.util.*; + +public class Example { + private String user; + private String[] list; + public example(String user, String[] list) { + this.user = user; + this.list = list; + } + + public String view() { + StringBuffer _buf = new StringBuffer(); + +_buf.append("\n" + + " \n" + + "

    Hello "); _buf.append(user); _buf.append("!

    \n" + + " \n" + + " \n"); + for (int i = 0; i < list.length; i++) { +_buf.append(" \n" + + " \n" + + " \n" + + " \n"); + } +_buf.append(" \n" + + "
    "); _buf.append(i + 1); _buf.append(""); _buf.append(escape(list[i])); _buf.append("
    \n" + + " \n" + + "\n"); + + return _buf.toString(); + } + + public static void main(String[] args) { + String[] list = { "", "b&b", "\"ccc\"" }; + Example ex = Example.new("Erubis", list); + System.out.print(ex.view()); + } + + public static String escape(String s) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '<': sb.append("<"); break; + case '>': sb.append(">"); break; + case '&': sb.append("&"); break; + case '"': sb.append("""); break; + default: sb.append(ch); + } + } + return sb.toString(); + } +} + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_js.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_js.result new file mode 100644 index 0000000..f93f910 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_js.result @@ -0,0 +1,22 @@ +$ erubis -l js example.ejs +var _buf = []; + var user = 'Erubis'; + var list = ['', 'b&b', '"ccc"']; + +_buf.push("\n\ + \n\ +

    Hello "); _buf.push(user); _buf.push("!

    \n\ + \n\ + \n"); + var i; + for (i = 0; i < list.length; i++) { +_buf.push(" \n\ + \n\ + \n\ + \n"); + } +_buf.push(" \n\ +
    "); _buf.push(i + 1); _buf.push(""); _buf.push(list[i]); _buf.push("
    \n\ + \n\ +\n"); +document.write(_buf.join("")); diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_perl.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_perl.result new file mode 100644 index 0000000..3efbb73 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_perl.result @@ -0,0 +1,20 @@ +$ erubis -l perl example.eperl +use HTML::Entities; + my $user = 'Erubis'; + my @list = ('', 'b&b', '"ccc"'); + +print(' + +

    Hello '); print($user); print('!

    + +'); $i = 0; + for $item (@list) { +print(' + + + +'); } +print('
    '); print($i); print(''); print($item); print('
    + + +'); diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_php.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_php.result new file mode 100644 index 0000000..b9fa7d0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_php.result @@ -0,0 +1,19 @@ +$ erubis -l php example.ephp +<?xml version="1.0"?> + + +

    Hello !

    + + + + + + + + + + + +
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_scheme.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_scheme.result new file mode 100644 index 0000000..0bfb1e0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_scheme.result @@ -0,0 +1,30 @@ +$ erubis -l scheme example.escheme +(let ((_buf '())) (define (_add x) (set! _buf (cons x _buf))) (_add " + \n") + +(let ((user "Erubis") + (items '("" "b&b" "\"ccc\"")) + (i 0)) + +(_add "

    Hello ")(_add user)(_add "!

    + \n") + + (for-each + (lambda (item) + (set! i (+ i 1)) + +(_add " + + + \n") + + ) ; lambda end + items) ; for-each end + +(_add "
    ")(_add i)(_add "")(_add item)(_add "
    \n") + +) ; let end + +(_add " +\n") + (reverse _buf)) diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_scheme_display.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_scheme_display.result new file mode 100644 index 0000000..1481e51 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/example_scheme_display.result @@ -0,0 +1,29 @@ +$ erubis -l scheme --func=display example.escheme +(display " + \n") + +(let ((user "Erubis") + (items '("" "b&b" "\"ccc\"")) + (i 0)) + +(display "

    Hello ")(display user)(display "!

    + \n") + + (for-each + (lambda (item) + (set! i (+ i 1)) + +(display " + + + \n") + + ) ; lambda end + items) ; for-each end + +(display "
    ")(display i)(display "")(display item)(display "
    \n") + +) ; let end + +(display " +\n") diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby-example.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby-example.rb new file mode 100644 index 0000000..425ef0b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby-example.rb @@ -0,0 +1,8 @@ +require 'erubis' +input = File.read('example.eruby') + +puts "----- Erubis::Eruby -----" +print Erubis::Eruby.new(input).src + +puts "----- Erubis::FastEruby -----" +print Erubis::FastEruby.new(input).src diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby-example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby-example.result new file mode 100644 index 0000000..40319f7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby-example.result @@ -0,0 +1,18 @@ +$ ruby fasteruby-example.rb +----- Erubis::Eruby ----- +_buf = ''; _buf << '
    +'; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end + _buf << '
    +'; +_buf.to_s +----- Erubis::FastEruby ----- +_buf = ''; _buf << %Q`
    \n` + for item in list + _buf << %Q`

    #{ item }

    +

    #{Erubis::XmlHelper.escape_xml( item )}

    \n` + end + _buf << %Q`
    \n` +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.rb new file mode 100644 index 0000000..e336147 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.rb @@ -0,0 +1,11 @@ +require 'erubis' +input = File.read('fasteruby.rhtml') +eruby = Erubis::FastEruby.new(input) # create Eruby object + +puts "---------- script source ---" +puts eruby.src + +puts "---------- result ----------" +context = { :title=>'Example', :list=>['aaa', 'bbb', 'ccc'] } +output = eruby.evaluate(context) +print output diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.result new file mode 100644 index 0000000..fa1cb58 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.result @@ -0,0 +1,38 @@ +$ ruby fasteruby.rb +---------- script source --- +_buf = ''; _buf << %Q` + +

    #{Erubis::XmlHelper.escape_xml( @title )}

    + \n` + i = 0 + for item in @list + i += 1 + _buf << %Q` + + + \n` + end + _buf << %Q`
    #{ i }#{Erubis::XmlHelper.escape_xml( item )}
    + +\n` +_buf.to_s +---------- result ---------- + + +

    Example

    + + + + + + + + + + + + + +
    1aaa
    2bbb
    3ccc
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.rhtml new file mode 100644 index 0000000..9c526c4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/fasteruby.rhtml @@ -0,0 +1,15 @@ + + +

    <%== @title %>

    + +<% i = 0 %> +<% for item in @list %> +<% i += 1 %> + + + + +<% end %> +
    <%= i %><%== item %>
    + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example.eruby new file mode 100644 index 0000000..e4708bb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example.eruby @@ -0,0 +1,9 @@ + +<% for item in items %> + <%= item %> +<% end %> + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example2.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example2.rb new file mode 100644 index 0000000..5247296 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example2.rb @@ -0,0 +1,8 @@ +require 'erubis' +class HeaderFooterEruby < Erubis::Eruby + include Erubis::HeaderFooterEnhancer +end + +input = File.read('headerfooter-example2.rhtml') +eruby = HeaderFooterEruby.new(input) +print eruby.src diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example2.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example2.rhtml new file mode 100644 index 0000000..520c037 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter-example2.rhtml @@ -0,0 +1,10 @@ + + + + : + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter_example.result new file mode 100644 index 0000000..58ab90d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter_example.result @@ -0,0 +1,11 @@ +$ erubis -xE HeaderFooter headerfooter-example.eruby + +def list_items(items) + +_buf = ''; for item in items + _buf << ' '; _buf << ( item ).to_s; _buf << ' +'; end +_buf.to_s + +end + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter_example2.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter_example2.result new file mode 100644 index 0000000..147fc54 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/headerfooter_example2.result @@ -0,0 +1,13 @@ +$ erubis -xE HeaderFooter headerfooter-example2.rhtml + +def page(list) + +_buf = ''; _buf << ' + +'; _buf << ' : +'; _buf << ' +'; +_buf.to_s + +end + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/interpolation_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/interpolation_example.result new file mode 100644 index 0000000..a96a685 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/interpolation_example.result @@ -0,0 +1,9 @@ +$ erubis -xE DeleteIndent example.eruby +_buf = ''; _buf << '
    +'; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end + _buf << '
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program1.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program1.rb new file mode 100644 index 0000000..dd4d349 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program1.rb @@ -0,0 +1,8 @@ +require 'erubis' +eruby = Erubis::Eruby.new(File.read('template1.rhtml')) +items = ['foo', 'bar', 'baz'] +x = 1 +## local variable 'x' and 'eruby' are passed to template as well as 'items'! +print eruby.result(binding()) +## local variable 'x' is changed unintendedly because it is changed in template! +puts "** debug: x=#{x.inspect}" #=> "baz" diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program1.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program1.result new file mode 100644 index 0000000..8e8c653 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program1.result @@ -0,0 +1,6 @@ +$ ruby main_program1.rb +item = foo +item = bar +item = baz +** debug: local variables=["eruby", "items", "x", "_buf"] +** debug: x="baz" diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program2.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program2.rb new file mode 100644 index 0000000..0d5883b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program2.rb @@ -0,0 +1,8 @@ +require 'erubis' +eruby = Erubis::Eruby.new(File.read('template2.rhtml')) +items = ['foo', 'bar', 'baz'] +x = 1 +## only 'items' are passed to template +print eruby.evaluate(:items=>items) +## local variable 'x' is not changed! +puts "** debug: x=#{x.inspect}" #=> 1 diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program2.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program2.result new file mode 100644 index 0000000..f95fa05 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/main_program2.result @@ -0,0 +1,6 @@ +$ ruby main_program2.rb +item = foo +item = bar +item = baz +** debug: local variables=["_context", "x", "_buf"] +** debug: x=1 diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode-example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode-example.eruby new file mode 100644 index 0000000..f0ed27a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode-example.eruby @@ -0,0 +1,14 @@ +

    List

    +<% if !@list || @list.empty? %> +

    not found.

    +<% else %> + + + <% @list.each_with_index do |item, i| %> + + + + <% end %> + +
    <%= item %>
    +<% end %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode-php.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode-php.result new file mode 100644 index 0000000..f331243 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode-php.result @@ -0,0 +1,20 @@ +$ erubis -l php --pi=php -N -E NoCode --trim=false notext-example.php + 1: + 2: + 3:

    List

    + 4: + 5:

    not found.

    + 6: + 7: + 8: + 9: + 10: + 11: + 12: + 13: + 14: + 15: + 16:
    + 17: + 18: + 19: diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode_example.result new file mode 100644 index 0000000..c6c2601 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/nocode_example.result @@ -0,0 +1,15 @@ +$ erubis -xE NoCode notext-example.eruby +

    List

    + +

    not found.

    + + + + + + + + + +
    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/normal-eruby-test.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/normal-eruby-test.eruby new file mode 100644 index 0000000..81bd711 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/normal-eruby-test.eruby @@ -0,0 +1,9 @@ +<% +def list_items(items) +%> +<% for item in items %> +
  • <%= item %>
  • +<% end %> +<% +end +%> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/normal_eruby_test.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/normal_eruby_test.result new file mode 100644 index 0000000..01016a7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/normal_eruby_test.result @@ -0,0 +1,11 @@ +$ erubis -x normal-eruby-test.eruby +_buf = ''; +def list_items(items) + + for item in items + _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • +'; end + +end + +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-example.eruby new file mode 100644 index 0000000..f0ed27a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-example.eruby @@ -0,0 +1,14 @@ +

    List

    +<% if !@list || @list.empty? %> +

    not found.

    +<% else %> + + + <% @list.each_with_index do |item, i| %> + + + + <% end %> + +
    <%= item %>
    +<% end %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-example.php b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-example.php new file mode 100644 index 0000000..c40cb91 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-example.php @@ -0,0 +1,19 @@ + + +

    List

    + +

    not found.

    + + + + + + + + + + +
    + + + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-php.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-php.result new file mode 100644 index 0000000..249e62c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext-php.result @@ -0,0 +1,20 @@ +$ erubis -l php --pi=php -N -E NoText --trim=false notext-example.php + 1: + 2: + 3: + 4: + 5: + 6: + 7: + 8: + 9: + 10: + 11: + 12: + 13: + 14: + 15: + 16: + 17: + 18: + 19: diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext_example.result new file mode 100644 index 0000000..dccbaca --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/notext_example.result @@ -0,0 +1,16 @@ +$ erubis -xE NoText notext-example.eruby +_buf = ''; + if !@list || @list.empty? + + else + + + @list.each_with_index do |item, i| + _buf << ( i%2 == 0 ? '#FFCCCC' : '#CCCCFF' ).to_s; + _buf << ( item ).to_s; + + end + + + end +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/percentline-example.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/percentline-example.rhtml new file mode 100644 index 0000000..eac00ed --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/percentline-example.rhtml @@ -0,0 +1,6 @@ +
      +% for item in list +
    • <%= item %>
    • +% end +
    +%% lines with '%%' diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/percentline_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/percentline_example.result new file mode 100644 index 0000000..5d21eb4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/percentline_example.result @@ -0,0 +1,9 @@ +$ erubis -xE PercentLine percentline-example.rhtml +_buf = ''; _buf << '
      +'; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • +'; end + _buf << '
    +% lines with \'%%\' +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline-example.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline-example.rb new file mode 100644 index 0000000..20c19f7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline-example.rb @@ -0,0 +1,9 @@ +require 'erubis' + +class PrefixedLineEruby < Erubis::Eruby + include Erubis::PrefixedLineEnhancer +end + +input = File.read('prefixedline-example.rhtml') +eruby = PrefixedLineEruby.new(input, :prefixchar=>'!') # default '%' +print eruby.src diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline-example.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline-example.rhtml new file mode 100644 index 0000000..a950df2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline-example.rhtml @@ -0,0 +1,6 @@ +
      + ! for item in list +
    • <%= item %>
    • + ! end +
    + !! lines with '!!' diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline_example.result new file mode 100644 index 0000000..9741b8a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/prefixedline_example.result @@ -0,0 +1,9 @@ +$ ruby prefixedline-example.rb +_buf = ''; _buf << '
      +'; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • +'; end + _buf << '
    + ! lines with \'!!\' +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenable_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenable_example.result new file mode 100644 index 0000000..69fb91c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenable_example.result @@ -0,0 +1,4 @@ +$ ruby printenabled-example.rb + aaa + bbb + ccc diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenabled-example.eruby b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenabled-example.eruby new file mode 100644 index 0000000..84b345f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenabled-example.eruby @@ -0,0 +1,3 @@ +<% for item in @list %> + <% print item %> +<% end %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenabled-example.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenabled-example.rb new file mode 100644 index 0000000..289964c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printenabled-example.rb @@ -0,0 +1,8 @@ +require 'erubis' +class PrintEnabledEruby < Erubis::Eruby + include Erubis::PrintEnabledEnhancer +end +input = File.read('printenabled-example.eruby') +eruby = PrintEnabledEruby.new(input) +list = ['aaa', 'bbb', 'ccc'] +print eruby.evaluate(:list=>list) diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printstatement_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printstatement_example.result new file mode 100644 index 0000000..49fcd81 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/printstatement_example.result @@ -0,0 +1,8 @@ +$ erubis -xE PrintOut example.eruby + print '
    +'; for item in list + print '

    '; print(( item ).to_s); print '

    +

    '; print Erubis::XmlHelper.escape_xml( item ); print '

    +'; end + print '
    +'; diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/simplify_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/simplify_example.result new file mode 100644 index 0000000..82022ce --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/simplify_example.result @@ -0,0 +1,9 @@ +$ erubis -xE Simplify example.eruby +_buf = ''; _buf << '
    +'; for item in list ; _buf << ' +

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end ; _buf << ' +
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stderr.log b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stderr.log new file mode 100644 index 0000000..422f276 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stderr.log @@ -0,0 +1,3 @@ +*** debug: item="" +*** debug: item="b&b" +*** debug: item="\"ccc\"" diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stdout_exmple.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stdout_exmple.result new file mode 100644 index 0000000..c5a714d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stdout_exmple.result @@ -0,0 +1,9 @@ +$ erubis -xE Stdout example.eruby +_buf = $stdout; _buf << '
    +'; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end + _buf << '
    +'; +'' diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stringbuffer_example.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stringbuffer_example.result new file mode 100644 index 0000000..75e9894 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/stringbuffer_example.result @@ -0,0 +1,9 @@ +$ erubis -xE StringBuffer example.eruby +_buf = ''; _buf << '
    +'; for item in list + _buf << '

    '; _buf << ( item ).to_s; _buf << '

    +

    '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '

    +'; end + _buf << '
    +'; +_buf.to_s diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/tail_260.result b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/tail_260.result new file mode 100644 index 0000000..7163bcd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/tail_260.result @@ -0,0 +1,4 @@ +$ erubis -c '{var: "AAA\n"}' tailnewline.rhtml +
    +AAA +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/tailnewline.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/tailnewline.rhtml new file mode 100644 index 0000000..8674daa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/tailnewline.rhtml @@ -0,0 +1,3 @@ +
    +<%= @var -%> +
    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/template1.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/template1.rhtml new file mode 100644 index 0000000..2b88b6b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/template1.rhtml @@ -0,0 +1,4 @@ +<% for x in items %> +item = <%= x %> +<% end %> +** debug: local variables=<%= local_variables().inspect() %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/template2.rhtml b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/template2.rhtml new file mode 100644 index 0000000..f5df553 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/data/users-guide/template2.rhtml @@ -0,0 +1,4 @@ +<% for x in @items %> +item = <%= x %> +<% end %> +** debug: local variables=<%= local_variables().inspect() %> diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-engines.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-engines.rb new file mode 100644 index 0000000..3d61dfd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-engines.rb @@ -0,0 +1,425 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require "#{File.dirname(__FILE__)}/test.rb" + +require 'erubis' +require 'erubis/engine/eruby' +require 'erubis/engine/ephp' +require 'erubis/engine/ec' +require 'erubis/engine/ecpp' +require 'erubis/engine/ejava' +require 'erubis/engine/escheme' +require 'erubis/engine/eperl' +require 'erubis/engine/ejavascript' + + +class EnginesTest < Test::Unit::TestCase + + #load_yaml_documents(__FILE__) + testdata_list = load_yaml_datafile(__FILE__) + define_testmethods(testdata_list) + + def _test() + klass = Erubis.const_get(@class) + engine = klass.new(@input, @options || {}) + actual = engine.src + assert_text_equal(@expected, actual) + end + + + self.post_definition() + +end + +__END__ +- name: ruby1 + lang: ruby + class: Eruby + options: + input: | + + + <% i = 0 + list.each_with_index do |item, i| %> + + + + + <% end %> + +
    <%= i+1 %><%== list %>
    + <%=== i+1 %> + expected: | + _buf = ''; _buf << ' + + '; i = 0 + list.each_with_index do |item, i| + _buf << ' + + + + '; end + _buf << ' +
    '; _buf << ( i+1 ).to_s; _buf << ''; _buf << Erubis::XmlHelper.escape_xml( list ); _buf << '
    + '; $stderr.puts("*** debug: i+1=#{(i+1).inspect}"); _buf << ' + '; + _buf.to_s +## +- name: ruby2_options + lang: ruby + class: Eruby + options: { :bufvar: '@_out_buf' } + input: | + + <% for item in @items %> + + + + + <% end %> +
    <%= i+1 %><%== list %>
    + expected: | + @_out_buf = ''; @_out_buf << ' + '; for item in @items + @_out_buf << ' + + + + '; end + @_out_buf << '
    '; @_out_buf << ( i+1 ).to_s; @_out_buf << ''; @_out_buf << Erubis::XmlHelper.escape_xml( list ); @_out_buf << '
    + '; + @_out_buf.to_s +## +- name: php1 + lang: php + class: Ephp + options: + input: | + + + <% + $i = 0; + foreach ($list as $item) { + $i++; + %> + + + + + <% + } + %> + +
    <%= $i %><%== $item %>
    + <%=== $i %> + expected: | + + + + + + + + + +
    + +## +- name: c1 + lang: c + class: Ec + options: { :filename: foo.html, :indent: ' ' } + input: |4 + + + <% for (i = 0; i < list; i++) { %> + + + + + <% } %> + +
    <%= "%d", i %><%== list[i] %>
    + <%=== "%d", i %> + expected: | + #line 1 "foo.html" + fputs("\n" + " \n", stdout); + for (i = 0; i < list; i++) { + fputs(" \n" + " \n" + " \n" + " \n", stdout); + } + fputs(" \n" + "
    ", stdout); fprintf(stdout, "%d", i); fputs("", stdout); escape(list[i], stdout); fputs("
    \n", stdout); + fprintf(stderr, "*** debug: i=" "%d", i); fputs("\n", stdout); +## +- name: cpp1 + lang: cpp + class: Ecpp + options: { :filename: foo.html, :indent: ' ' } + input: |4 + + + <% for (i = 0; i < n; i++) { %> + + + + + <% } %> + +
    <%= i %><%== list[i] %>
    + <%=== i %> + expected: | + #line 1 "foo.html" + _buf << "\n" + " \n"; + for (i = 0; i < n; i++) { + _buf << " \n" + " \n" + " \n" + " \n"; + } + _buf << " \n" + "
    "; _buf << (i); _buf << ""; escape(list[i]); _buf << "
    \n"; + std::cerr << "*** debug: i=" << (i); _buf << "\n"; +## +- name: java1 + lang: java + class: Ejava + options: { :buf: _buf, :bufclass: StringBuilder, :indent: ' ' } + input: | + + + <% + int i = 0; + for (Iterator it = list.iterator(); it.hasNext(); ) { + String s = (String)it.next(); + i++; + %> + "> + + + + <% + } + %> + +
    <%= i %><%== s %>
    + <%=== i %> + expected: |4 + StringBuilder _buf = new StringBuilder(); _buf.append("\n" + + " \n"); + + int i = 0; + for (Iterator it = list.iterator(); it.hasNext(); ) { + String s = (String)it.next(); + i++; + + _buf.append(" \n" + + " \n" + + " \n" + + " \n"); + + } + + _buf.append(" \n" + + "
    "); _buf.append(i); _buf.append(""); _buf.append(escape(s)); _buf.append("
    \n"); + System.err.println("*** debug: i="+(i)); _buf.append("\n"); + return _buf.toString(); +## +- name: scheme1 + lang: scheme + class: Escheme + options: + input: &scheme1_input| + <% (let ((i 0)) %> + + + <% + (for-each + (lambda (item) + (set! i (+ i 1)) + %> + + + + + <% + ); lambda end + list); for-each end + %> + +
    <%= i %><%== item %>
    + <%=== i %> + <% ); let end %> + expected: |4 + (let ((_buf '())) (define (_add x) (set! _buf (cons x _buf))) (let ((i 0)) + (_add " + \n") + + (for-each + (lambda (item) + (set! i (+ i 1)) + + (_add " + + + \n") + + ); lambda end + list); for-each end + + (_add " +
    ")(_add i)(_add "")(_add (escape item))(_add "
    \n") + (display "*** debug: i=")(display i)(display "\n")(_add "\n") + ); let end + (reverse _buf)) + +## +- name: scheme2 + lang: scheme + class: Escheme + options: { :func: 'display' } + input: *scheme1_input + expected: |4 + (let ((i 0)) + (display " + \n") + + (for-each + (lambda (item) + (set! i (+ i 1)) + + (display " + + + \n") + + ); lambda end + list); for-each end + + (display " +
    ")(display i)(display "")(display (escape item))(display "
    \n") + (display "*** debug: i=")(display i)(display "\n")(display "\n") + ); let end +## +- name: perl1 + lang: perl + class: Eperl + options: + input: | + <% + my $user = 'Erubis'; + my @list = ('', 'b&b', '"ccc"'); + %> +

    Hello <%= $user %>!

    + + + <% $i = 0; %> + <% for $item (@list) { %> + "> + + + + <% } %> + +
    <%= $i %><%== $item %>
    + <%=== $i %> + expected: |4 + use HTML::Entities; + my $user = 'Erubis'; + my @list = ('', 'b&b', '"ccc"'); + + print('

    Hello '); print($user); print('!

    + + + '); $i = 0; + for $item (@list) { + print(' + + + + '); } + print(' +
    '); print($i); print(''); print(encode_entities($item)); print('
    + '); print('*** debug: $i=', $i, "\n");print(' + '); +## +- name: javascript1 + lang: javascript + class: Ejavascript + options: + input: &javascript_input | + <% + var user = 'Erubis'; + var list = ['', 'b&b', '"ccc"']; + %> +

    Hello <%= user %>!

    + + + <% var i; %> + <% for (i = 0; i < list.length; i++) { %> + "> + + + + <% } %> + +
    <%= i %><%= list[i] %>
    + <%=== i %> + expected: |4 + var _buf = []; + var user = 'Erubis'; + var list = ['', 'b&b', '"ccc"']; + + _buf.push("

    Hello "); _buf.push(user); _buf.push("!

    \n\ + \n\ + \n"); + var i; + for (i = 0; i < list.length; i++) { + _buf.push(" \n\ + \n\ + \n\ + \n"); + } + _buf.push(" \n\ +
    "); _buf.push(i); _buf.push(""); _buf.push(list[i]); _buf.push("
    \n"); + alert("*** debug: i="+(i)); _buf.push("\n"); + document.write(_buf.join("")); + ## +- name: javascript2 + lang: javascript + class: Ejavascript + options: { :docwrite: false } + input: *javascript_input + expected: |4 + var _buf = []; + var user = 'Erubis'; + var list = ['', 'b&b', '"ccc"']; + + _buf.push("

    Hello "); _buf.push(user); _buf.push("!

    \n\ + \n\ + \n"); + var i; + for (i = 0; i < list.length; i++) { + _buf.push(" \n\ + \n\ + \n\ + \n"); + } + _buf.push(" \n\ +
    "); _buf.push(i); _buf.push(""); _buf.push(list[i]); _buf.push("
    \n"); + alert("*** debug: i="+(i)); _buf.push("\n"); + _buf.join(""); + ## diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-enhancers.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-enhancers.rb new file mode 100644 index 0000000..fac9589 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-enhancers.rb @@ -0,0 +1,646 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require "#{File.dirname(__FILE__)}/test.rb" + +require 'stringio' + +require 'erubis' +require 'erubis/engine/enhanced' +require 'erubis/engine/optimized' + + +class EnhancersTest < Test::Unit::TestCase + + testdata_list = load_yaml_datafile(__FILE__) + define_testmethods(testdata_list) + + + def _test() + @src.gsub!(/\^/, ' ') + @output.gsub!(/\^/, ' ') if @output.is_a?(String) + if @class + k = Erubis + @class.split('::').each do |name| k = k.const_get(name) end + @klass = k + else + @klass = Erubis::Eruby + end + @options ||= {} + @chomp.each do |target| + case target + when 'src' ; @src.chomp! + when 'input' ; @input.chomp! + when 'expected' ; @expected.chomp! + else + raise "#{@name}: invalid chomp value: #{@chomp.inspect}" + end + end if @chomp + + if @testopt == 'load_file' + filename = "tmp.#{@name}.eruby" + begin + File.open(filename, 'w') { |f| f.write(@input) } + eruby = @klass.load_file(filename, @options) + ensure + cachename = filename + '.cache' + File.unlink(cachename) if test(?f, cachename) + File.unlink(filename) if test(?f, filename) + end + else + #if @klass == Erubis::TinyEruby + # eruby = @klass.new(@input) + #else + eruby = @klass.new(@input, @options) + #end + end + assert_text_equal(@src, eruby.src) + + return if @testopt == 'skip_output' + + list = ['', 'b&b', '"ccc"'] + context = @testopt == 'context' ? Erubis::Context.new : {} + context[:list] = list + + case @testopt + when /\Aeval\(/ + eval eruby.src + actual = eval @testopt + assert_text_equal(@output, actual) + when 'stdout', 'print' + begin + orig = $stdout + $stdout = stringio = StringIO.new + #actual = eruby.evaluate(context) + actual = eruby.result(context) + ensure + $stdout = orig + end + if @testopt == 'stdout' + assert_equal("", actual) + else + assert_nil(actual) + end + assert_text_equal(@output, stringio.string) + when 'evaluate', 'context' + actual = eruby.evaluate(context) + assert_text_equal(@output, actual) + when 'binding' + actual = eruby.result(binding()) + assert_text_equal(@output, actual) + else + actual = eruby.result(context) + assert_text_equal(@output, actual) + end + end + + + self.post_definition() + +end + +__END__ + +## +- name: basic1 + class: Eruby + input: &basic1_input| +
      + <% for item in list %> +
    • <%= item %>
    • + <% end %> +
    + src: &basic1_src| + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: &basic1_output| +
      +
    • +
    • b&b
    • +
    • "ccc"
    • +
    + +- name: xml1 + class: XmlEruby + input: | +
    +       <% for item in list %>
    +        <%= item %>
    +        <%== item %>
    +       <% end %>
    +      
    + src: | + _buf = ''; _buf << '
    +      ';  for item in list 
    +       _buf << '  '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
    +      '; _buf << '  '; _buf << ( item ).to_s; _buf << '
    +      ';  end 
    +       _buf << '
    + '; + _buf.to_s + output: | +
    +        <aaa>
    +        
    +        b&b
    +        b&b
    +        "ccc"
    +        "ccc"
    +      
    + +## +- name: xml2 + class: XmlEruby + testopt: skip_output + input: | + <% for item in list %> + <%= item["var#{n}"] %> + <%== item["var#{n}"] %> + <%=== item["var#{n}"] %> + <%==== item["var#{n}"] %> + <% end %> + src: | + _buf = ''; for item in list + _buf << ' '; _buf << Erubis::XmlHelper.escape_xml( item["var#{n}"] ); _buf << ' + '; _buf << ' '; _buf << ( item["var#{n}"] ).to_s; _buf << ' + '; _buf << ' '; $stderr.puts("*** debug: item[\"var\#{n}\"]=#{(item["var#{n}"]).inspect}"); _buf << ' + '; _buf << ' '; _buf << ' + '; end + _buf.to_s + output: | + +## +- name: printout1 + class: PrintOutEruby + testopt: print + input: *basic1_input + src: |4 + print '
      + '; for item in list + print '
    • '; print(( item ).to_s); print '
    • + '; end + print '
    + '; + output: *basic1_output + +## +- name: printenabled1 + class: PrintEnabledEruby + input: &printenabled1_input| +
      + <% for item in list %> +
    • <% print item %>
    • + <% end %> +
    + src: | + @_buf = _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; print item ; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output +#
      +#
    • +#
    • b&b
    • +#
    • "ccc"
    • +#
    + +## +- name: stdout1 + class: StdoutEruby + testopt: stdout + input: *basic1_input +#
      +# <% for item in list %> +#
    • <%= item %>
    • +# <% end %> +#
    + src: | + _buf = $stdout; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + '' + output: *basic1_output +#
      +#
    • +#
    • b&b
    • +#
    • "ccc"
    • +#
    + +## +- name: array1 + class: ArrayEruby + input: | +
      + <% for item in list %> +
    • <%= item %>
    • + <% end %> +
    + src: | + _buf = []; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf + output: + - "
      \n" + - "
    • " + - "" + - "
    • \n" + - "
    • " + - "b&b" + - "
    • \n" + - "
    • " + - "\"ccc\"" + - "
    • \n" + - "
    \n" + +## +- name: arraybuffer1 + class: ArrayBufferEruby + input: *basic1_input + src: | + _buf = []; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.join + output: *basic1_output + +- name: stringbuffer1 + class: StringBufferEruby + input: *basic1_input +#
      +# <% for item in list %> +#
    • <%= item %>
    • +# <% end %> +#
    + src: | + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output +#
      +#
    • +#
    • b&b
    • +#
    • "ccc"
    • +#
    + +## +- name: erbout1 + class: ErboutEruby + input: *basic1_input + src: | + _erbout = _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output + +## +- name: stringio1 + class: StringIOEruby + input: *basic1_input + src: | + _buf = StringIO.new; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.string + output: *basic1_output + +## +- name: notext1 + class: NoTextEruby + input: *basic1_input + src: | + _buf = ''; + for item in list + _buf << ( item ).to_s; + end + + _buf.to_s + output: 'b&b"ccc"' + + +## +- name: nocode1 + class: NoCodeEruby + testopt: skip_output + input: *basic1_input + src: | +
      + +
    • + +
    + output: + +## +- name: simplified + class: SimplifiedEruby + input: | +
      + <% for item in list %> +
    • + <%= item %> +
    • + <% end %> +
    + src: | + _buf = ''; _buf << '
      + '; for item in list ; _buf << ' +
    • + '; _buf << ( item ).to_s; _buf << ' +
    • + '; end ; _buf << ' +
    + '; + _buf.to_s + output: | +
      + ^ +
    • + +
    • + ^ +
    • + b&b +
    • + ^ +
    • + "ccc" +
    • + ^ +
    + +## +- name: bipattern1 + class: BiPatternEruby + #options: { :bipattern : '\[= =\]' } + input: | + <% for item in list %> + <%= item %> % <%== item %> + [= item =] = [== item =] + <% end %> + src: | + _buf = ''; for item in list + _buf << ' '; _buf << ( item ).to_s; _buf << ' % '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << ' + '; _buf << ' '; _buf << ( item ).to_s; _buf << ' = '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << ' + '; end + _buf.to_s + output: |4 + % <aaa> + = <aaa> + b&b % b&b + b&b = b&b + "ccc" % "ccc" + "ccc" = "ccc" + +## +- name: bipattern2 + class: BiPatternEruby + options: { :bipattern: '\$\{ \}' } + input: | + <% for item in list %> + <%=item%> % <%==item%> + ${item} = ${=item} + <% end %> + src: | + _buf = ''; for item in list + _buf << ' '; _buf << (item).to_s; _buf << ' % '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << ' + '; _buf << ' '; _buf << (item).to_s; _buf << ' = '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << ' + '; end + _buf.to_s + output: |4 + % <aaa> + = <aaa> + b&b % b&b + b&b = b&b + "ccc" % "ccc" + "ccc" = "ccc" + +## +- name: percentline1 + class: PercentLineEruby + options: + input: | + + % for item in list + + + + + % end +
    <%= item %><%== item %>
    +
    +      %% double percent
    +       % spaced percent
    +      
    + src: | + _buf = ''; _buf << ' + '; for item in list + _buf << ' + + + + '; end + _buf << '
    '; _buf << ( item ).to_s; _buf << ''; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
    +
    +      % double percent
    +       % spaced percent
    +      
    + '; + _buf.to_s + output: | + + + + + + + + + + + + + +
    <aaa>
    b&bb&b
    "ccc""ccc"
    +
    +      % double percent
    +       % spaced percent
    +      
    + +## +- name: prefixedline1 + class: PrefixedLineEruby + options: { :prefixchar: '!' } + input: | + + ! for item in list + + + + + ! end +
    <%= item %><%== item %>
    +
    +        !! doubled characters
    +      
    + src: | + _buf = ''; _buf << ' + '; for item in list + _buf << ' + + + + '; end + _buf << '
    '; _buf << ( item ).to_s; _buf << ''; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
    +
    +        ! doubled characters
    +      
    + '; + _buf.to_s + output: | + + + + + + + + + + + + + +
    <aaa>
    b&bb&b
    "ccc""ccc"
    +
    +        ! doubled characters
    +      
    + +## +- name: headerfooter1 + class: HeaderFooterEruby + options: + testopt: eval('ordered_list(list)') + input: | + +
      + <% for item in list %> +
    1. <%==item%>
    2. + <% end %> +
    + + src: |4 + + def ordered_list(list) + + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    1. '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '
    2. + '; end + _buf << '
    + '; + _buf.to_s + end + output: | +
      +
    1. <aaa>
    2. +
    3. b&b
    4. +
    5. "ccc"
    6. +
    + +## +- name: deleteindent1 + class: DeleteIndentEruby + options: + testopt: + input: *basic1_input + src: | + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: | +
      +
    • +
    • b&b
    • +
    • "ccc"
    • +
    + +## +- name: interpolation1 + class: InterpolationEruby + options: + testopt: + input: *basic1_input + src: | + _buf = ''; _buf << %Q`
      \n` + for item in list + _buf << %Q`
    • #{ item }
    • \n` + end + _buf << %Q`
    \n` + _buf.to_s + output: *basic1_output + +- name: interpolation2 + desc: sharp, back-quote, and backslash should be escaped, but other quotes should not be escaped (reported by andrewj) + class: InterpolationEruby + options: + testopt: + input: | +

    `back-quote`

    +

    <%= `echo back-tick operator` %>

    +

    #{sharp}

    +

    'single quote'

    +

    "double quote"

    +

    backslash\n\t

    + src: | + _buf = ''; _buf << %Q`

    \`back-quote\`

    +

    #{ `echo back-tick operator` }

    +

    \#{sharp}

    +

    'single quote'

    +

    "double quote"

    +

    backslash\\n\\t

    \n` + _buf.to_s + output: | +

    `back-quote`

    +

    back-tick operator +

    +

    #{sharp}

    +

    'single quote'

    +

    "double quote"

    +

    backslash\n\t

    diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-erubis.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-erubis.rb new file mode 100644 index 0000000..39f300e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-erubis.rb @@ -0,0 +1,887 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require "#{File.dirname(__FILE__)}/test.rb" + +require 'stringio' + +require 'erubis' +require 'erubis/engine/enhanced' +require 'erubis/engine/optimized' +require 'erubis/tiny' + + +class ErubisTest < Test::Unit::TestCase + + testdata_list = load_yaml_datafile(__FILE__) + define_testmethods(testdata_list) + + + def _test() + @src.gsub!(/\^/, ' ') + @output.gsub!(/\^/, ' ') if @output.is_a?(String) + if @class + k = Erubis + @class.split('::').each do |name| k = k.const_get(name) end + @klass = k + else + @klass = Erubis::Eruby + end + @options ||= {} + @chomp.each do |target| + case target + when 'src' ; @src.chomp! + when 'input' ; @input.chomp! + when 'expected' ; @expected.chomp! + else + raise "#{@name}: invalid chomp value: #{@chomp.inspect}" + end + end if @chomp + + if @testopt == 'load_file' + filename = "tmp.#{@name}.eruby" + begin + File.open(filename, 'w') { |f| f.write(@input) } + eruby = @klass.load_file(filename, @options) + ensure + cachename = filename + '.cache' + File.unlink(cachename) if test(?f, cachename) + File.unlink(filename) if test(?f, filename) + end + else + if @klass == Erubis::TinyEruby + eruby = @klass.new(@input) + else + eruby = @klass.new(@input, @options) + end + end + assert_text_equal(@src, eruby.src) + + return if @testopt == 'skip_output' + + list = ['', 'b&b', '"ccc"'] + context = @testopt == 'context' ? Erubis::Context.new : {} + context[:list] = list + + case @testopt + when /\Aeval\(/ + eval eruby.src + actual = eval @testopt + assert_text_equal(@output, actual) + when 'stdout', 'print' + begin + orig = $stdout + $stdout = stringio = StringIO.new + #actual = eruby.evaluate(context) + actual = eruby.result(context) + ensure + $stdout = orig + end + if @testopt == 'stdout' + assert_equal("", actual) + else + assert_nil(actual) + end + assert_text_equal(@output, stringio.string) + when 'evaluate', 'context' + actual = eruby.evaluate(context) + assert_text_equal(@output, actual) + when 'binding' + actual = eruby.result(binding()) + assert_text_equal(@output, actual) + else + actual = eruby.result(context) + assert_text_equal(@output, actual) + end + end + + + def test_load_file_cache1 + @input = < +<% for item in @list %> +
  • <%= item %>
  • +<% end %> + +END + @src = < +'; for item in @list + _buf << '
  • '; _buf << ( item ).to_s; _buf << '
  • +'; end + _buf << ' +'; +_buf.to_s +END + @klass = Erubis::Eruby + filename = 'tmp.load_file_timestamp1' + cachename = filename + '.cache' + begin + ## when cache doesn't exist then it is created automatically + File.open(filename, 'w') { |f| f.write(@input) } + mtime = Time.now - 2.0 + File.utime(mtime, mtime, filename) + !test(?f, cachename) or raise "** failed" + engine = @klass.load_file(filename) + assert_block() { test(?f, cachename) } + assert_block() { File.mtime(filename) <= File.mtime(cachename) } + assert_text_equal(@src, engine.src) + ## when cache has different timestamp then it is recreated + input2 = @input.gsub(/ul>/, 'ol>') + src2 = @src.gsub(/ul>/, 'ol>') + File.open(filename, 'w') { |f| f.write(input2) } + t1 = Time.now() + sleep(1) + t2 = Time.now() + # + File.utime(t1, t1, filename) + File.utime(t2, t2, cachename) + File.mtime(filename) < File.mtime(cachename) or raise "** failed" + engine = @klass.load_file(filename) + assert_block('cache should have same timestamp') { File.mtime(filename) == File.mtime(cachename) } + #assert_text_equal(@src, engine.src) + assert_text_equal(src2, engine.src) + # + File.utime(t2, t2, filename) + File.utime(t1, t1, cachename) + File.mtime(filename) > File.mtime(cachename) or raise "** failed" + engine = @klass.load_file(filename) + assert_block('cache should have same timestamp') { File.mtime(filename) == File.mtime(cachename) } + assert_text_equal(src2, engine.src) + ensure + File.unlink(cachename) if File.file?(cachename) + File.unlink(filename) if File.file?(filename) + end + end + + + class Dummy + end + + def _class_has_instance_method(klass, method) + return klass.instance_methods.collect{|m| m.to_s}.include?(method.to_s) + end + + def test_def_method1 + s = "<%for i in list%>i=<%=i%>\n<%end%>" + eruby = Erubis::Eruby.new(s) + assert(! _class_has_instance_method(Dummy, 'render')) + eruby.def_method(Dummy, 'render(list)', 'foo.rhtml') + assert(_class_has_instance_method(Dummy, 'render')) + actual = Dummy.new().render(%w[1 2 3]) + assert_equal("i=1\ni=2\ni=3\n", actual) + end + + def test_def_method2 + s = "<%for i in list%>i=<%=i%>\n<%end%>" + eruby = Erubis::Eruby.new(s) + assert(! (eruby.respond_to? :render)) + eruby.def_method(eruby, 'render(list)', 'foo.rhtml') + assert eruby.respond_to?(:render) + actual = eruby.render([1, 2, 3]) + assert_equal("i=1\ni=2\ni=3\n", actual) + assert(! _class_has_instance_method(eruby.class, 'render')) + end + + def test_evaluate_creates_proc + s = "hello <%= @name %>" + eruby = Erubis::Eruby.new(s) + assert_nil(eruby.instance_variable_get('@_proc')) + actual1 = eruby.evaluate(:name=>'world') + assert_not_nil(eruby.instance_variable_get('@_proc')) + assert_instance_of(Proc, eruby.instance_variable_get('@_proc')) + actual2 = eruby.evaluate(:name=>'world') + assert_equal(actual1, actual2) + # convert() must clear @_proc + eruby.convert(s) + assert_nil(eruby.instance_variable_get('@_proc')) + end + + #def test_toplevel_binding + # s = "locals = <%= local_variables().inspect %>\n<% x = 50 %>\n" + # eruby = Erubis::Eruby.new(s) + # _x = eval 'x', TOPLEVEL_BINDING + # _y = eval 'y', TOPLEVEL_BINDING + # actual = eruby.evaluate(:x=>_x, :y=>_y) + # _x = eval 'x', TOPLEVEL_BINDING + # _y = eval 'y', TOPLEVEL_BINDING + # puts "*** actual=#{actual.inspect}, x=#{_x.inspect}, y=#{_y.inspect}" + #end + + self.post_definition() + +end + +x = 10 +y = 20 + + +__END__ +- name: basic1 + input: &basic1_input| +
      + <% for item in list %> +
    • <%= item %>
    • + <% end %> +
    + src: &basic1_src| + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: &basic1_output| +
      +
    • +
    • b&b
    • +
    • "ccc"
    • +
    + +## +- name: basic2 + input: | +
      + <% i = 0 + for item in list + i += 1 + %> +
    • <%= item %>
    • + <% end %> +
    + src: | + _buf = ''; _buf << '
      + '; i = 0 + for item in list + i += 1 + ^^^ + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output +#
      +#
    • +#
    • b&b
    • +#
    • "ccc"
    • +#
    + +## +- name: basic3 + input: | +
      <% i = 0 + for item in list + i += 1 %>
    • <%= item %>
    • <% end %> +
    + src: | + _buf = ''; _buf << '
      '; i = 0 + for item in list + i += 1 ; _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • '; end ; _buf << ' + '; _buf << '
    + '; + _buf.to_s + output: | +
    • b&b
    • "ccc"
    • +
    + +## +- name: context1 + testopt: context + input: | +
      + <% for item in @list %> +
    • <%= item %>
    • + <% end %> +
    + src: | + _buf = ''; _buf << '
      + '; for item in @list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output + +## +- name: ignore1 + input: | +
      + <%# i = 0 %> + <% for item in list %> + <%# + i += 1 + color = i % 2 == 0 ? '#FFCCCC' : '#CCCCFF' + %> +
    • <%#= i %> : <%= item %>
    • + <% end %> +
    + src: | + _buf = ''; _buf << '
      + '; + for item in list + + + + + _buf << '
    • ';; _buf << ' : '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: | +
      +
    • :
    • +
    • : b&b
    • +
    • : "ccc"
    • +
    + +## +- name: quotation1 + desc: single quotation and backslash + class: Eruby + input: "ation1_input| + a = "'" + b = "\"" + c = '\'' + src: | + _buf = ''; _buf << 'a = "\'" + b = "\\"" + c = \'\\\'\' + '; + _buf.to_s + output: *quotation1_input + +## +- name: minus1 + desc: '<%- -%>' + class: Eruby + input: | +
      + <%- for item in list -%> +
    • <%= item -%>
    • + <% end -%> +
    + src: *basic1_src + output: *basic1_output + +## +- name: pattern1 + options: + :pattern : '\[@ @\]' + input: | +
      + [@ for item in list @] +
    • [@= item @]
    • + [@ end @] +
    + src: | + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output +#
      +#
    • +#
    • b&b
    • +#
    • "ccc"
    • +#
    + +## +- name: pattern2 + options: + :pattern : '<(?:!--)?% %(?:--)?>' + input: | +
      + +
    • <%= item %>
    • + +
    + src: | + _buf = ''; _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: *basic1_output +#
      +#
    • +#
    • b&b
    • +#
    • "ccc"
    • +#
    + +## +- name: trim1 + options: + :trim : false + input: *basic1_input +#
      +# <% for item in list %> +#
    • <%= item %>
    • +# <% end %> +#
    + src: | + _buf = ''; _buf << '
      + '; _buf << ' '; for item in list ; _buf << ' + '; _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; _buf << ' '; end ; _buf << ' + '; _buf << '
    + '; + _buf.to_s + output: | +
      + ^ +
    • + ^ +
    • b&b
    • + ^ +
    • "ccc"
    • + ^ +
    + +## +- name: bodyonly1 + testopt: skip_output + options: { :preamble: no, :postamble: no } + input: *basic1_input + src: |4 + _buf << '
      + '; for item in list + _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + chomp: [src] + expected: null + +## +- name: loadfile1 + testopt: load_file + #input: | + #
      + # <% for item in list %> + #
    • <%= item %>
    • + # <% end %> + #
    + input: + "
      \r\n <% for item in list %>\r\n
    • <%= item %>
    • \r\n <% end %>\r\n
    \r\n" + #src: | + # _buf = ''; _buf << "
      \n" + # for item in list + # _buf << "
    • "; _buf << ( item ).to_s; _buf << "
    • \n" + # end + # _buf << "
    \n" + # _buf + src: + "_buf = ''; _buf << '
      \r\n'; for item in list \r\n _buf << '
    • '; _buf << ( item ).to_s; _buf << '
    • \r\n'; end \r\n _buf << '
    \r\n';\n_buf.to_s\n" + #output: | + #
      + #
    • + #
    • b&b
    • + #
    • "ccc"
    • + #
    + output: + "
      \n
    • \n
    • b&b
    • \n
    • \"ccc\"
    • \n
    \n" + # "
      \r\n
    • \r\n
    • b&b
    • \r\n
    • \"ccc\"
    • \r\n
    \r\n" + +## +- name: nomatch1 + desc: bug + input: &nomatch1| +
      +
    • foo
    • +
    + src: | + _buf = ''; _buf << '
      +
    • foo
    • +
    + '; + _buf.to_s + output: *nomatch1 + +## +- name: escape1 + options: { :escape: true } + input: | + <% str = '<>&"' %> + <%= str %> + <%== str %> + src: | + _buf = ''; str = '<>&"' + _buf << Erubis::XmlHelper.escape_xml( str ); _buf << ' + '; _buf << ( str ).to_s; _buf << ' + '; + _buf.to_s + output: | + <>&" + <>&" + +## +- name: tailch1 + options: + input: | +

    + <% str = '<>&"' %> + <%= str %> + <%= str =%> + <%= str -%> +

    + src: | + _buf = ''; _buf << '

    + '; str = '<>&"' + _buf << ' '; _buf << ( str ).to_s; _buf << ' + '; _buf << ' '; _buf << ( str ).to_s; _buf << ' '; _buf << ( str ).to_s; _buf << '

    + '; + _buf.to_s + output: | +

    + <>&" + <>&" <>&"

    + +## +- name: doublepercent1 + options: + input: | + <% x1 = 10 %> + <%% x2 = 20 %> + <%= x1 %> + <%%= x2 %> + src: | + _buf = ''; x1 = 10 + _buf << '<% x2 = 20 %> + '; _buf << ( x1 ).to_s; _buf << ' + '; _buf << '<%= x2 %> + '; + _buf.to_s + output: | + <% x2 = 20 %> + 10 + <%= x2 %> + +## +- name: optimized1 + class: OptimizedEruby + input: &optimized1_input| + + <% for item in list %> + + + + + <% end %> +
    <%= item %><%== item %>
    +
      <% for item in list %>
    • <%= item %>
    • <% end %>
    + src: | + _buf = ' + '; for item in list + _buf << ' + + + + '; end + _buf << '
    ' << ( item ).to_s << '' << Erubis::XmlHelper.escape_xml( item ) << '
    +
      '; for item in list ; _buf << '
    • ' << ( item ).to_s << '
    • '; end ; _buf << '
    + ' + _buf + output: | + + + + + + + + + + + + + +
    <aaa>
    b&bb&b
    "ccc""ccc"
    +
    • b&b
    • "ccc"
    + +## +- name: optimized2 + class: OptimizedXmlEruby + input: *optimized1_input +# +# <% for item in list %> +# +# +# +# +# <% end %> +#
    <%= item %><%== item %>
    +#
      <% for item in list %>
    • <%= item %>
    • <% end %>
    + src: | + _buf = ' + '; for item in list + _buf << ' + + + + '; end + _buf << '
    ' << Erubis::XmlHelper.escape_xml( item ) << '' << ( item ).to_s << '
    +
      '; for item in list ; _buf << '
    • ' << Erubis::XmlHelper.escape_xml( item ) << '
    • '; end ; _buf << '
    + ' + _buf + output: | + + + + + + + + + + + + + +
    <aaa>
    b&bb&b
    "ccc""ccc"
    +
    • <aaa>
    • b&b
    • "ccc"
    + +## +- name: optimized3 + desc: bug + class: OptimizedEruby + input: | + user = <%= "Foo" %> + <% for item in list %> + <%= item %> + <% end %> + src: | + _buf = 'user = '; _buf << ( "Foo" ).to_s << ' + '; for item in list + _buf << ' ' << ( item ).to_s << ' + '; end + + _buf + output: | + user = Foo + + b&b + "ccc" + +## +- name: optimized4 + desc: single quotation and backslash + class: OptimizedEruby + input: &optimized4_input| + a = "'" + b = "\"" + c = '\'' + src: | + _buf = 'a = "\'" + b = "\\"" + c = \'\\\'\' + '; + _buf + output: *optimized4_input + +## +- name: tiny1 + class: TinyEruby + testopt: binding + input: | +
      + <% for item in list %> +
    • <%= item %>
    • + <% end %> +
    + src: | + _buf = ''; _buf << '
      + '; for item in list ; _buf << ' +
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end ; _buf << ' +
    + '; + _buf.to_s + output: | +
      + ^ +
    • + ^ +
    • b&b
    • + ^ +
    • "ccc"
    • + ^ +
    + +## +- name: tiny2 + class: TinyEruby + testopt: evaluate + input: | +
      + <% for item in @list %> +
    • <%= item %>
    • + <% end %> +
    + src: | + _buf = ''; _buf << '
      + '; for item in @list ; _buf << ' +
    • '; _buf << ( item ).to_s; _buf << '
    • + '; end ; _buf << ' +
    + '; + _buf.to_s + output: | +
      + ^ +
    • + ^ +
    • b&b
    • + ^ +
    • "ccc"
    • + ^ +
    + +## +- name: pi1 + class: PI::Eruby + testopt: evaluate + input: &input_pi1| +
      + +
    • @{item}@ / @!{item}@
    • +
    • <%= item %> / <%== item %>
    • + +
    + src: &src_pi1| + _buf = ''; _buf << '
      + '; for item in @list + _buf << '
    • '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << ' / '; _buf << (item).to_s; _buf << '
    • +
    • '; _buf << ( item ).to_s; _buf << ' / '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: &output_pi1| +
      +
    • <aaa> /
    • +
    • / <aaa>
    • +
    • b&b / b&b
    • +
    • b&b / b&b
    • +
    • "ccc" / "ccc"
    • +
    • "ccc" / "ccc"
    • +
    + +## +- name: pi2 + class: PI::Eruby + options: { :escape: false } + testopt: evaluate + input: *input_pi1 + src: | + _buf = ''; _buf << '
      + '; for item in @list + _buf << '
    • '; _buf << (item).to_s; _buf << ' / '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << '
    • +
    • '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << ' / '; _buf << ( item ).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: | +
      +
    • / <aaa>
    • +
    • <aaa> /
    • +
    • b&b / b&b
    • +
    • b&b / b&b
    • +
    • "ccc" / "ccc"
    • +
    • "ccc" / "ccc"
    • +
    + +## +- name: pi3 + class: PI::Eruby + options: { :pi: hoge, :embchar: '$' } + testopt: evaluate + input: | +
      + +
    • ${item}$ / $!{item}$
    • +
    • <%= item %> / <%== item %>
    • + +
    + src: *src_pi1 + output: *output_pi1 + +- name: pi4 + class: PI::Eruby + testopt: evaluate + input: | + +
      + + + + +
    + + + src: |4 + + def show(list) + + _buf = ''; _buf << '
      + '; for item in list + _buf << ( item + ).to_s; end + + + + + _buf << '
    + '; + _buf.to_s + + end + show(@list) + + output: | +
      + b&b"ccc"
    + + +- name: pitiny1 + class: PI::TinyEruby + testopt: evaluate + input: | +
      + +
    • @{item}@ / @!{item}@
    • + +
    + src: | + _buf = ''; _buf << '
      + '; for item in @list + _buf << '
    • '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << ' / '; _buf << (item).to_s; _buf << '
    • + '; end + _buf << '
    + '; + _buf.to_s + output: | +
      +
    • <aaa> /
    • +
    • b&b / b&b
    • +
    • "ccc" / "ccc"
    • +
    + diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-index-cgi.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-index-cgi.rb new file mode 100644 index 0000000..bf364bd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-index-cgi.rb @@ -0,0 +1,191 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + +require "#{File.dirname(__FILE__)}/test.rb" + +require 'stringio' + +load "#{File.dirname(__FILE__)}/../public_html/index.cgi" + + +def spec(desc) + yield +end + + +def dummy_env(request_method='GET', request_uri='/', opts={}) + if request_method.is_a?(Hash) + opts = request_method + request_method = 'GET' + request_uri = '/' + elsif request_uri.is_a?(Hash) + opts = request_uri + request_uri = '/' + end + env = { + 'REQUEST_METHOD' => request_method.to_s, + 'REQUEST_URI' => request_uri.to_s, + 'DOCUMENT_ROOT' => Dir.pwd, + } + opts.each {|k, v| env[k.to_s.upcase] = v } + env.update(opts) + return env +end + + +def dummy_template(filename, content) + begin + File.open(filename, 'wb') {|f| f.write(content) } + return yield + ensure + [filename, filename + '.cache'].each do |fname| + File.unlink(fname) if File.exist?(fname) + end + end +end + + +class ErubisHandlerTest < Test::Unit::TestCase + + def test_initialize + + spec "sets @encoding and @layout" do + encoding_bkup = $ENCODING + layout_bkup = $LAYOUT + begin + $ENCODING = 'cp932' + $LAYOUT = 'site.rhtml' + obj = ErubisHandler.new + assert_equal 'cp932', obj.encoding + assert_equal 'site.rhtml', obj.layout + ensure + $ENCODING = encoding_bkup + $LAYOUT = layout_bkup + end + end + + end + + def test_handle + + spec "renders requested template file." do + base = "_test_handle" + env = dummy_env('GET', "/#{base}.html") + handler = ErubisHandler.new + input = <<'END' +

    <%= 'SOS' %>

    +
      + <% for item in %w[Haruhi Mikuru Yuki] %> +
    • <%= item %>
    • + <% end %> +
    +END + expected = <<'END' +

    SOS

    +
      +
    • Haruhi
    • +
    • Mikuru
    • +
    • Yuki
    • +
    +END + out = dummy_template("#{base}.rhtml", input) do + handler.handle(env) + end + assert_equal expected, out + end + + spec "raises 404 error when requested file not found." do + req_url = "/_test_handle.html" + env = dummy_env('GET', req_url) + handler = ErubisHandler.new + ex = assert_raise HttpError do + handler.handle(env) + end + assert_equal 404, ex.status + assert_equal "#{req_url}: not found.", ex.message + end + + end + +end + + +class ErubisApplicationTest < Test::Unit::TestCase + + def test_handle_request + + spec "handles request by handler object and returns response data." do + app = ErubisApplication.new() + def app.get_handler + return Class.new { + def handle(env); "

    Hello SOS

    "; end + def encoding; "euc_jp"; end + }.new + end + expected = [ + 200, + [["Content-Type", "text/html;charset=euc_jp"]], + ["

    Hello SOS

    "], + ] + env = dummy_env('GET', '/') + ret = app.call(env) + assert_equal expected, ret + end + + end + + def test_handle_http_error + + spec "renders error page." do + req_path = '/HaruhiSuzumiya.html' + app = ErubisApplication.new() + env = dummy_env('GET', req_path) + expected = [ + 404, + [["Content-Type", "text/html"]], + ["

    404 Not Found

    \n

    #{req_path}: not found.

    \n"], + ] + ret = app.call(env) + assert_equal expected, ret + end + + end + + def test_run + + spec "prints to $stdout" do + input = "

    Hello SOS

    " + app = ErubisApplication.new + base = "SOS" + env = dummy_env("GET", "/#{base}.html") + sio = StringIO.new + output = dummy_template("#{base}.rhtml", input) do + app.run(env, sio) + sio.string + end + expected = "" + expected << "Content-Type: text/html\r\n" + expected << "\r\n" + expected << "

    Hello SOS

    " + assert_equal expected, output + end + + spec "prints 'Status:' header if status code is not 200." do + req_path = "/SOS.html" + env = dummy_env("GET", req_path) + app = ErubisApplication.new + sio = StringIO.new + app.run(env, sio) + expected = "Status: 404 Not Found\r\n" + expected << "Content-Type: text/html\r\n" + expected << "\r\n" + expected << "

    404 Not Found

    \n" + expected << "

    #{req_path}: not found.

    \n" + assert_equal expected, sio.string + end + + end + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-main.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-main.rb new file mode 100644 index 0000000..c96298d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-main.rb @@ -0,0 +1,752 @@ +## +## $Rev$ +## $Release: 2.7.0 $ +## $Date$ +## + +require "#{File.dirname(__FILE__)}/test.rb" + +require 'tempfile' +require 'fileutils' +require 'erubis/main' + + +$script = File.dirname(TESTDIR) + '/bin/erubis' +#if test(?f, 'bin/erubis') +# $script = 'bin/erubis' +#elsif test(?f, '../bin/erubis') +# $script = '../bin/erubis' +#end + + +class StringWriter < String + def write(arg) + self << arg + end + def flush(*args) + # pass + end + def puts(arg) + case arg + when Array + arg.each do |item| + self << item << "\n" + end + else + self << arg.to_s + self << "\n" unless arg =~ /\n$/ + end + end +end + +class Erubis::Main + public :usage + public :show_properties + public :show_enhancers +end + + +class MainTest < Test::Unit::TestCase + + INPUT = <<'END' +list: +<% list = ['', 'b&b', '"ccc"'] + for item in list %> + - <%= item %> +<% end %> +user: <%= defined?(user) ? user : "(none)" %> +END + INPUT2 = INPUT.gsub(/\blist([^:])/, '@list\1').gsub(/\buser([^:])/, '@user\1') + +# SRC = <<'END' +#_buf = ''; _buf << "list:\n" +# list = ['', 'b&b', '"ccc"'] +# for item in list +#_buf << " - "; _buf << ( item ).to_s; _buf << "\n" +# end +#_buf << "user: "; _buf << ( defined?(user) ? user : "(none)" ).to_s; _buf << "\n" +#_buf +#END + SRC = <<'END' +_buf = ''; _buf << 'list: +'; list = ['', 'b&b', '"ccc"'] + for item in list + _buf << ' - '; _buf << ( item ).to_s; _buf << ' +'; end + _buf << 'user: '; _buf << ( defined?(user) ? user : "(none)" ).to_s; _buf << ' +'; +_buf.to_s +END +# SRC2 = SRC.gsub(/\blist /, '@list ').gsub(/\buser /, '@user ') + + OUTPUT = <<'END' +list: + - + - b&b + - "ccc" +user: (none) +END + + ESCAPED_OUTPUT = <<'END' +list: + - <aaa> + - b&b + - "ccc" +user: (none) +END + + + PI_INPUT = <<'END' +
      + ', 'b&b', '"ccc"'] + for item in @list ?> +
    • @{item}@ / @!{item}@ + <%= item %> / <%== item %>
    • + +
        +END + + PI_SRC = <<'END' +_buf = ''; _buf << '
          +'; @list = ['', 'b&b', '"ccc"'] + for item in @list + _buf << '
        • '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << ' / '; _buf << (item).to_s; _buf << ' + '; _buf << ( item ).to_s; _buf << ' / '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '
        • +'; end + _buf << '
            +'; +_buf.to_s +END + + PI_ESCAPED_SRC = <<'END' +_buf = ''; _buf << '
              +'; @list = ['', 'b&b', '"ccc"'] + for item in @list + _buf << '
            • '; _buf << (item).to_s; _buf << ' / '; _buf << Erubis::XmlHelper.escape_xml(item); _buf << ' + '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << ' / '; _buf << ( item ).to_s; _buf << '
            • +'; end + _buf << '
                +'; +_buf.to_s +END + + PI_OUTPUT = <<'END' +
                  +
                • <aaa> / + / <aaa>
                • +
                • b&b / b&b + b&b / b&b
                • +
                • "ccc" / "ccc" + "ccc" / "ccc"
                • +
                    +END + + PI_ESCAPED_OUTPUT = <<'END' +
                      +
                    • / <aaa> + <aaa> /
                    • +
                    • b&b / b&b + b&b / b&b
                    • +
                    • "ccc" / "ccc" + "ccc" / "ccc"
                    • +
                        +END + + def _test() + if @filename.nil? + method = (caller[0] =~ /in `(.*)'/) && $1 #' + method =~ /block in (.*)/ and method = $1 # for Ruby 1.9 + @filename = "tmp.#{method}" + end + File.open(@filename, 'w') {|f| f.write(@input) } if @filename + begin + argv = @options.is_a?(Array) ? @options.dup : @options.split + argv << @filename if @filename + $stdout = output = StringWriter.new + Erubis::Main.new.execute(argv) + ensure + $stdout = STDOUT + File.unlink(@filename) if @filename && test(?f, @filename) + end + assert_text_equal(@expected, output) + end + + def _error_test(errclass, errmsg) + ex = assert_raise(errclass) { _test() } + assert_equal(errmsg, ex.message) + end + + + def test_help # -h + @options = '-h' + m = Erubis::Main.new + @expected = m.usage() + "\n" + m.show_properties() + m.show_enhancers() + @filename = false + _test() + end + + def test_version # -v + @options = '-v' + @expected = (("$Release: 2.7.0 $" =~ /[.\d]+/) && $&) + "\n" + @filename = false + _test() + end + + + def test_basic1 + @input = INPUT + @expected = OUTPUT + @options = '' + _test() + end + + + def test_source1 # -x + @input = INPUT + @expected = SRC + @options = '-x' + _test() + end + + + def _with_dummy_file + bindir = File.join(File.dirname(File.dirname(__FILE__)), 'bin') + env_path = ENV['PATH'] + env__ = ENV['_'] + begin + ENV['PATH'] = bindir + File::PATH_SEPARATOR + ENV['PATH'] + ENV['_'] = 'erubis' + Tempfile.open(self.name.gsub(/[^\w]/,'_')) do |f| + f.write(INPUT) + f.flush + yield(f.path) + end + ensure + ENV['PATH'] = env_path + ENV['_'] = env__ if env__ + end + end + + + def test_syntax1 # -z (syntax ok) + @input = INPUT + @expected = "Syntax OK\n" + @options = '-z' + _test() + # + _with_dummy_file do |filepath| + actual = `erubis #{@options} #{filepath}` + assert_equal @expected, actual + end + end + + + def test_syntax2 # -z (syntax error) + inputs = [] + inputs << <<'END' +
                          +<% for item in list %> +
                        • <%= item[:name]] %>
                        • +<% end %> +
                        +END + inputs << <<'END' +
                          +<% for item in list %> +
                        • <%= item[:name] %>
                        • +<% edn %> +
                        +END + basename = 'tmp.test_syntax2_%d.rhtml' + filenames = [ basename % 0, basename % 1 ] + errmsgs = [] + if ruby19? + errmsgs << <<'END' +3: syntax error, unexpected ']', expecting ')' + _buf << '
                      • '; _buf << ( item[:name]] ).to_s; _buf << '
                      • + ^ +-:4: syntax error, unexpected keyword_end, expecting ')' +'; end + ^ +-:7: syntax error, unexpected $end, expecting ')' +END + errmsgs << <<'END' +7: syntax error, unexpected $end, expecting keyword_end +END + elsif rubinius? + errmsgs << <<'END' +3: expecting ')' + _buf << '
                      • '; _buf << ( item[:name]] ).to_s; _buf << '
                      • + ^ +END + errmsgs << <<'END' +7: missing 'end' for 'for' started on line 2 +_buf.to_s + ^ +END + else + errmsgs << <<'END' +3: syntax error, unexpected ']', expecting ')' + _buf << '
                      • '; _buf << ( item[:name]] ).to_s; _buf << '
                      • + ^ +-:4: syntax error, unexpected kEND, expecting ')' +'; end + ^ +-:7: syntax error, unexpected $end, expecting ')' +END + errmsgs << <<'END' +7: syntax error, unexpected $end, expecting kEND +END + end + # + max = inputs.length + (0...max).each do |i| + @input = inputs[i] + @expected = "tmp.test_syntax2:#{errmsgs[i]}" + @options = '-z' + if rubinius? + @expected.sub! /unexpected kEND/, 'unexpected keyword_end' + @expected.sub! /expecting kEND/, 'expecting keyword_end' + end + _test() + end + # + begin + (0...max).each do |i| + File.open(filenames[i], 'w') {|f| f.write(inputs[i]) } + end + @input = '' + @expected = '' + @options = '-z' + (0...max).each do |i| + @expected << "#{filenames[i]}:#{errmsgs[i]}" + @options << " #{filenames[i]}" + end + if rubinius? + @expected.sub! /unexpected kEND/, 'unexpected keyword_end' + @expected.sub! /expecting kEND/, 'expecting keyword_end' + end + _test() + ensure + (0...max).each do |i| + File.unlink(filenames[i]) if test(?f, filenames[i]) + end + end + end + + + def test_pattern1 # -p + @input = INPUT.gsub(/<%/, '') + @expected = OUTPUT + #@options = "-p ''" + @options = ["-p", ""] + _test() + end + + +# def test_class1 # -C +# @input = INPUT +# @expected = OUTPUT.gsub(//, '<aaa>').gsub(/b&b/, 'b&b').gsub(/"ccc"/, '"ccc"') +# @options = "-C XmlEruby" +# _test() +# end + + + def test_notrim1 # --trim=false + @input = INPUT + @expected = <<'END' +list: + + - + + - b&b + + - "ccc" + +user: (none) +END + @options = "--trim=false" # -T + _test() + end + + + def test_notrim2 # --trim=false + @input = INPUT +# @expected = <<'END' +#_buf = ''; _buf << "list:\n" +# list = ['', 'b&b', '"ccc"'] +# for item in list ; _buf << "\n" +#_buf << " - "; _buf << ( item ).to_s; _buf << "\n" +# end ; _buf << "\n" +#_buf << "user: "; _buf << ( defined?(user) ? user : "(none)" ).to_s; _buf << "\n" +#_buf +#END + @expected = <<'END' +_buf = ''; _buf << 'list: +'; list = ['', 'b&b', '"ccc"'] + for item in list ; _buf << ' +'; _buf << ' - '; _buf << ( item ).to_s; _buf << ' +'; end ; _buf << ' +'; _buf << 'user: '; _buf << ( defined?(user) ? user : "(none)" ).to_s; _buf << ' +'; +_buf.to_s +END + @options = "-x --trim=false" # -xT + _test() + end + + + #-- + #def test_context1 + # @input = INPUT + # @expected = OUTPUT.gsub(/\(none\)/, 'Hello') + # @options = '--user=Hello' + # _test() + #end + #++ + + + def test_datafile1 # -f data.yaml + datafile = "test.context1.yaml" + @input = INPUT2 + @expected = OUTPUT.gsub(/\(none\)/, 'Hello') + @options = "-f #{datafile}" + # + str = <<-END + user: Hello + password: world + END + File.open(datafile, 'w') {|f| f.write(str) } + begin + _test() + ensure + File.unlink(datafile) if test(?f, datafile) + end + end + + + def test_datafile2 # -f data.rb + datafile = "test.context1.rb" + @input = INPUT2 + @expected = OUTPUT.gsub(/\(none\)/, 'Hello') + @options = "-f #{datafile}" + # + str = <<-END + @user = 'Hello' + @password = 'world' + END + File.open(datafile, 'w') {|f| f.write(str) } + begin + _test() + ensure + File.unlink(datafile) if test(?f, datafile) + end + end + + + def test_untabify1 # -t (obsolete) + yamlfile = "test.context2.yaml" + @input = INPUT2 + @expected = OUTPUT.gsub(/\(none\)/, 'Hello') + @options = "-tf #{yamlfile}" + # + yaml = <<-END + user: Hello + password: world + END + File.open(yamlfile, 'w') {|f| f.write(yaml) } + begin + _test() + ensure + File.unlink(yamlfile) if test(?f, yamlfile) + end + end + + + def test_untabify2 # -T + yamlfile = "test.context2.yaml" + @input = INPUT2 + @expected = OUTPUT.gsub(/\(none\)/, 'Hello') + @options = "-Tf #{yamlfile}" + # + yaml = <<-END + user: Hello + items: + - aaa + - bbb + - ccc + END + File.open(yamlfile, 'w') {|f| f.write(yaml) } + assert_raise(ArgumentError) do + _test() + end + File.open(yamlfile, 'w') {|f| f.write(yaml.gsub(/\t/, ' '*8)) } + _test() + ensure + File.unlink(yamlfile) if test(?f, yamlfile) + end + + + def test_symbolify1 # -S + yamlfile = "test.context3.yaml" + @input = < + + <%= h[:name] %><%= h[:mail] %> + +<% end %> +END + @expected = < + foofoo@mail.com + + + barbar@mail.org + +END + @options = "-f #{yamlfile} -S" + # + yaml = <<-END +list: + - name: foo + mail: foo@mail.com + - name: bar + mail: bar@mail.org +END + File.open(yamlfile, 'w') { |f| f.write(yaml) } + begin + _test() + ensure + File.unlink(yamlfile) if test(?f, yamlfile) + end + end + + + def test_result1 # -B + yamlfile = "test.context4.yaml" + # + @input = <<'END' +user = <%= user %> +<% for item in list %> + - <%= item %> +<% end %> +END + @expected = <<'END' +user = World + - aaa + - bbb + - ccc +END + @options = "-f #{yamlfile} -B " + # + yaml = <<-END +user: World +list: + - aaa + - bbb + - ccc +END + File.open(yamlfile, 'w') {|f| f.write(yaml) } + begin + _test() + ensure + File.unlink(yamlfile) if test(?f, yamlfile) + end + end + + + def test_context1 # -c + @input = <<'END' +user = <%= @user %> +<% for item in @list %> + - <%= item %> +<% end %> +END + @expected = <<'END' +user = World + - aaa + - bbb + - ccc +END + # + @options = ['-c', '{user: World, list: [aaa, bbb, ccc]}'] + _test() + @options = ['-c', '@user="World"; @list=%w[aaa bbb ccc]'] + _test() + end + + + def test_include1 # -I + dir = 'foo' + lib = 'bar' + Dir.mkdir dir unless test(?d, dir) + filename = "#{dir}/#{lib}.rb" + File.open(filename, 'w') do |f| + f.write <<-'END' + def escape(str) + return "<#{str.upcase}>" + end + END + end + # + @input = "<% require '#{lib}' %>\n" + INPUT.gsub(/<%= item %>/, '<%= escape(item) %>') + @expected = OUTPUT.gsub(//, '<>').gsub(/b\&b/, '').gsub(/"ccc"/, '<"CCC">') + @options = "-I #{dir}" + # + begin + _test() + ensure + File.unlink filename if test(?f, filename) + FileUtils.rm_r dir if test(?d, dir) + end + end + + + def test_require1 # -r + dir = 'foo' + lib = 'bar' + Dir.mkdir dir unless test(?d, dir) + filename = "#{dir}/#{lib}.rb" + File.open(filename, 'w') do |f| + f.write <<-'END' + def escape(str) + return "<#{str.upcase}>" + end + END + end + # + @input = INPUT.gsub(/<%= item %>/, '<%= escape(item) %>') + @expected = OUTPUT.gsub(//, '<>').gsub(/b\&b/, '').gsub(/"ccc"/, '<"CCC">') + @options = "-I #{dir} -r #{lib}" + # + begin + _test() + ensure + File.unlink filename if test(?f, filename) + FileUtils.rm_r dir if test(?d, dir) + end + end + + + def test_enhancers1 # -E + @input = < b&b "ccc"] %> +% for item in list + - <%= item %> : <%== item %> + - [= item =] : [== item =] +% end +END + @expected = < + - <aaa> : + - b&b : b&b + - b&b : b&b + - "ccc" : "ccc" + - "ccc" : "ccc" +END + @options = "-E Escape,PercentLine,HeaderFooter,BiPattern" + _test() + end + + + def test_bodyonly1 # -b + @input = INPUT + @expected = SRC.sub(/\A_buf = '';/,'').sub(/\n_buf.to_s\n\z/,'') + @options = '-b -x' + _test() + end + + + def test_escape1 # -e + @input = INPUT + @expected = SRC.gsub(/<< \((.*?)\).to_s;/, '<< Erubis::XmlHelper.escape_xml(\1);') + @options = '-ex' + _test() + end + + + def test_invalid_option # -1 (invalid option) + @input = INPUT + @options = '-1' + _error_test(Erubis::CommandOptionError, "-1: unknown option.") + end + + + def test_invalid_enhancer # -E hoge + @options = '-E hoge' + errmsg = "hoge: no such Enhancer (try '-h' to show all enhancers)." + _error_test(Erubis::CommandOptionError, errmsg) + end + + + def test_invalid_lang # -l hoge + @options = '-l hoge' + errmsg = "-l hoge: invalid language name (class Erubis::Ehoge not found)." + _error_test(Erubis::CommandOptionError, errmsg) + end + + + def test_missing_argument # -E + @filename = false + @options = '-E' + _error_test(Erubis::CommandOptionError, "-E: enhancers required.") + @options = '-l' + _error_test(Erubis::CommandOptionError, "-l: lang required.") + end + + + def test_pi1 # --pi -x + @input = PI_INPUT + @expected = PI_SRC + @options = '-x --pi' + _test() + end + + def test_pi2 # --pi -x --escape=false + @input = PI_INPUT + @expected = PI_ESCAPED_SRC + @options = '-x --pi --escape=false' + _test() + end + + def test_pi3 # --pi + @input = PI_INPUT + @expected = PI_OUTPUT + @options = '--pi' + _test() + end + + def test_pi4 # --pi --escape=false + @input = PI_INPUT + @expected = PI_ESCAPED_OUTPUT + @options = '--pi --escape=false' + _test() + end + + def test_pi5 # --pi=ruby -x + @input = PI_INPUT.gsub(/<\?rb/, ' + - @{arr[i]}@ / @!{arr[i]}@ + +END + @expected = <<'END' +StringBuffer _buf = new StringBuffer(); for (int i = 0; i < arr.length; i++) { +_buf.append(" - "); _buf.append(escape(arr[i])); _buf.append(" / "); _buf.append(arr[i]); _buf.append("\n"); + } +return _buf.toString(); +END + @options = '--pi -xl java' + _test() + end + + + self.post_definition() + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-users-guide.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-users-guide.rb new file mode 100644 index 0000000..a2ee68e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test-users-guide.rb @@ -0,0 +1,73 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require "#{File.dirname(__FILE__)}/test.rb" + + +class KwarkUsersGuideTest < Test::Unit::TestCase + + DIR = File.expand_path(File.dirname(__FILE__) + '/data/users-guide') + CWD = Dir.pwd() + + + def setup + Dir.chdir DIR + end + + + def teardown + Dir.chdir CWD + end + + + def _test + @name = (caller()[0] =~ /`(.*?)'/) && $1 + s = File.read(@filename) + s =~ /\A\$ (.*?)\n/ + command = $1 + expected = $' + if ruby19? + case @name + when 'test_main_program1_result' + expected.sub!('["eruby", "items", "x", "_buf"]', '[:_buf, :eruby, :items, :x]') + when 'test_main_program2_result' + expected.sub!('["_context", "x", "_buf"]', '[:_buf, :x, :_context]') + end + elsif rubinius? + command.sub!(/^ruby\b/, 'rbx') + case @name + when 'test_main_program1_result' + expected.sub!('["eruby", "items", "x", "_buf"]', '["_buf", "eruby", "items", "x"]') + when 'test_main_program2_result' + expected.sub!('["_context", "x", "_buf"]', '["_buf", "x", "_context"]') + end + end + result = `#{command}` + assert_text_equal(expected, result) + end + + + Dir.chdir DIR do + filenames = [] + filenames += Dir.glob('*.result') + filenames += Dir.glob('*.source') + filenames.each do |filename| + name = filename.gsub(/[^\w]/, '_') + s = <<-END + def test_#{name} + # $stderr.puts "*** debug: test_#{name}" + @name = '#{name}' + @filename = '#{filename}' + _test() + end + END + eval s + end + end + + + self.post_definition() + +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test.rb new file mode 100644 index 0000000..6dca713 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/test.rb @@ -0,0 +1,45 @@ +## +## $Release: 2.7.0 $ +## copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +## + + +unless defined?(TESTDIR) + TESTDIR = File.dirname(__FILE__) + LIBDIR = TESTDIR == '.' ? '../lib' : File.dirname(TESTDIR) + '/lib' + $: << TESTDIR + $: << LIBDIR +end + + +require 'test/unit' +#require 'test/unit/ui/console/testrunner' +require 'assert-text-equal' +require 'yaml' +require 'testutil' +require 'erubis' + + +Test::Unit::TestCase.class_eval do + if RUBY_VERSION >= "1.9" + ## minitest doesn't have 'name()' method + def name + @name || @__name__ + end + def ruby19 + yield + end + else + def ruby19 + end + end +end + + +if $0 == __FILE__ + require "#{TESTDIR}/test-erubis.rb" + require "#{TESTDIR}/test-engines.rb" + require "#{TESTDIR}/test-enhancers.rb" + require "#{TESTDIR}/test-main.rb" + require "#{TESTDIR}/test-users-guide.rb" +end diff --git a/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/testutil.rb b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/testutil.rb new file mode 100644 index 0000000..acc67c8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/erubis-2.7.0/test/testutil.rb @@ -0,0 +1,111 @@ +### +### $Release: 2.7.0 $ +### copyright(c) 2006-2011 kuwata-lab.com all rights reserved. +### + +require 'yaml' + +require 'test/unit/testcase' + + + +def ruby18? # :nodoc: + RUBY_VERSION =~ /\A1.8/ +end + +def ruby19? # :nodoc: + RUBY_VERSION =~ /\A1.9/ +end + +def rubinius? # :nodoc: + defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx" +end + + + +class Test::Unit::TestCase + + + def self.load_yaml_datafile(filename, options={}, &block) # :nodoc: + # read datafile + s = File.read(filename) + if filename =~ /\.rb$/ + s =~ /^__END__$/ or raise "*** error: __END__ is not found in '#{filename}'." + s = $' + end + # untabify + s = _untabify(s) unless options[:tabify] == false + # load yaml document + testdata_list = [] + YAML.load_documents(s) do |ydoc| + if ydoc.is_a?(Hash) + testdata_list << ydoc + elsif ydoc.is_a?(Array) + ydoc.each do |hash| + raise "testdata should be a mapping." unless hash.is_a?(Hash) + testdata_list << hash + end + else + raise "testdata should be a mapping." + end + end + # data check + identkey = options[:identkey] || 'name' + table = {} + testdata_list.each do |hash| + ident = hash[identkey] + ident or raise "*** key '#{identkey}' is required but not found." + table[ident] and raise "*** #{identkey} '#{ident}' is duplicated." + table[ident] = hash + yield(hash) if block + end + # + return testdata_list + end + + + def self.define_testmethods(testdata_list, options={}, &block) + identkey = options[:identkey] || 'name' + testmethod = options[:testmethod] || '_test' + testdata_list.each do |hash| + yield(hash) if block + ident = hash[identkey] + s = "def test_#{ident}\n" + hash.each do |key, val| + s << " @#{key} = #{val.inspect}\n" + end + s << " #{testmethod}\n" + s << "end\n" + $stderr.puts "*** load_yaml_testdata(): eval_str=<<'END'\n#{s}END" if $DEBUG + self.module_eval s + end + end + + + def self.post_definition + if ENV['TEST'] + target = "test_#{ENV['TEST']}" + self.instance_methods.each do |method_name| + m = method_name.to_s + private m if m =~ /\Atest_/ && m != target + end + end + end + + + def self._untabify(str, width=8) + return str if str.nil? + list = str.split(/\t/, -1) # if 2nd arg is negative then split() doesn't remove tailing empty strings + last = list.pop + sb = '' + list.each do |s| + column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length + n = width - (column % width) + sb << s << (' ' * n) + end + sb << last if last + return sb + end + + +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/LICENSE b/vendor/ruby/1.9.1/gems/execjs-1.3.0/LICENSE new file mode 100644 index 0000000..0db3dc6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2011 Sam Stephenson +Copyright (c) 2011 Josh Peek + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/README.md b/vendor/ruby/1.9.1/gems/execjs-1.3.0/README.md new file mode 100644 index 0000000..567ac4d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/README.md @@ -0,0 +1,47 @@ +ExecJS +====== + +ExecJS lets you run JavaScript code from Ruby. It automatically picks +the best runtime available to evaluate your JavaScript program, then +returns the result to you as a Ruby object. + +ExecJS supports these runtimes: + +* [therubyracer](https://github.com/cowboyd/therubyracer) - Google V8 + embedded within Ruby +* [therubyrhino](https://github.com/cowboyd/therubyrhino) - Mozilla + Rhino embedded within JRuby +* [Johnson](https://github.com/jbarnette/johnson) - Mozilla + SpiderMonkey embedded within Ruby +* [Mustang](https://github.com/nu7hatch/mustang) - Mustang V8 + embedded within Ruby +* [Node.js](http://nodejs.org/) +* Apple JavaScriptCore - Included with Mac OS X +* [Mozilla SpiderMonkey](http://www.mozilla.org/js/spidermonkey/) +* [Microsoft Windows Script Host](http://msdn.microsoft.com/en-us/library/9bbdkx3k.aspx) (JScript) + +A short example: + + require "execjs" + ExecJS.eval "'red yellow blue'.split(' ')" + # => ["red", "yellow", "blue"] + +A longer example, demonstrating how to invoke the CoffeeScript compiler: + + require "execjs" + require "open-uri" + source = open("http://jashkenas.github.com/coffee-script/extras/coffee-script.js").read + + context = ExecJS.compile(source) + context.call("CoffeeScript.compile", "square = (x) -> x * x", :bare => true) + # => "var square;\nsquare = function(x) {\n return x * x;\n};" + +# Installation + + $ gem install execjs + +# License + +Copyright (c) 2011 Sam Stephenson and Josh Peek. + +Released under the MIT license. See `LICENSE` for details. diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs.rb new file mode 100644 index 0000000..e6a3d09 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs.rb @@ -0,0 +1,6 @@ +require "execjs/module" +require "execjs/runtimes" + +module ExecJS + self.runtime ||= Runtimes.autodetect +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/disabled_runtime.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/disabled_runtime.rb new file mode 100644 index 0000000..961dc5b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/disabled_runtime.rb @@ -0,0 +1,23 @@ +module ExecJS + class DisabledRuntime + def name + "Disabled" + end + + def exec(source) + raise Error, "ExecJS disabled" + end + + def eval(source) + raise Error, "ExecJS disabled" + end + + def compile(source) + raise Error, "ExecJS disabled" + end + + def available? + true + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/external_runtime.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/external_runtime.rb new file mode 100644 index 0000000..7c1595f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/external_runtime.rb @@ -0,0 +1,213 @@ +require "shellwords" +require "tempfile" + +module ExecJS + class ExternalRuntime + class Context + def initialize(runtime, source = "") + source = source.encode('UTF-8') if source.respond_to?(:encode) + + @runtime = runtime + @source = source + end + + def eval(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + exec("return eval(#{MultiJson.encode("(#{source})")})") + end + end + + def exec(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + source = "#{@source}\n#{source}" if @source + + compile_to_tempfile(source) do |file| + extract_result(@runtime.send(:exec_runtime, file.path)) + end + end + + def call(identifier, *args) + eval "#{identifier}.apply(this, #{MultiJson.encode(args)})" + end + + protected + def compile_to_tempfile(source) + tempfile = Tempfile.open(['execjs', '.js']) + tempfile.write compile(source) + tempfile.close + yield tempfile + ensure + tempfile.close! + end + + def compile(source) + @runtime.send(:runner_source).dup.tap do |output| + output.sub!('#{source}') do + source + end + output.sub!('#{encoded_source}') do + encoded_source = encode_unicode_codepoints(source) + MultiJson.encode("(function(){ #{encoded_source} })()") + end + output.sub!('#{json2_source}') do + IO.read(ExecJS.root + "/support/json2.js") + end + end + end + + def extract_result(output) + status, value = output.empty? ? [] : MultiJson.decode(output) + if status == "ok" + value + elsif value =~ /SyntaxError:/ + raise RuntimeError, value + else + raise ProgramError, value + end + end + + if "".respond_to?(:codepoints) + def encode_unicode_codepoints(str) + str.gsub(/[\u0080-\uffff]/) do |ch| + "\\u%04x" % ch.codepoints.to_a + end + end + else + def encode_unicode_codepoints(str) + str.gsub(/([\xC0-\xDF][\x80-\xBF]| + [\xE0-\xEF][\x80-\xBF]{2}| + [\xF0-\xF7][\x80-\xBF]{3})+/nx) do |ch| + "\\u%04x" % ch.unpack("U*") + end + end + end + end + + attr_reader :name + + def initialize(options) + @name = options[:name] + @command = options[:command] + @runner_path = options[:runner_path] + @test_args = options[:test_args] + @test_match = options[:test_match] + @encoding = options[:encoding] + @binary = nil + end + + def exec(source) + context = Context.new(self) + context.exec(source) + end + + def eval(source) + context = Context.new(self) + context.eval(source) + end + + def compile(source) + Context.new(self, source) + end + + def available? + require "multi_json" + binary ? true : false + end + + private + def binary + @binary ||= locate_binary + end + + def locate_executable(cmd) + if ExecJS.windows? && File.extname(cmd) == "" + cmd << ".exe" + end + + if File.executable? cmd + cmd + else + path = ENV['PATH'].split(File::PATH_SEPARATOR).find { |p| + full_path = File.join(p, cmd) + File.executable?(full_path) && File.file?(full_path) + } + path && File.expand_path(cmd, path) + end + end + + protected + def runner_source + @runner_source ||= IO.read(@runner_path) + end + + def exec_runtime(filename) + output = sh("#{shell_escape(*(binary.split(' ') << filename))} 2>&1") + if $?.success? + output + else + raise RuntimeError, output + end + end + + def locate_binary + if binary = which(@command) + if @test_args + output = `#{shell_escape(binary, @test_args)} 2>&1` + binary if output.match(@test_match) + else + binary + end + end + end + + def which(command) + Array(command).find do |name| + name, args = name.split(/\s+/, 2) + path = locate_executable(name) + + next unless path + + args ? "#{path} #{args}" : path + end + end + + if "".respond_to?(:force_encoding) + def sh(command) + output, options = nil, {} + options[:external_encoding] = @encoding if @encoding + options[:internal_encoding] = Encoding.default_internal || 'UTF-8' + IO.popen(command, options) { |f| output = f.read } + output + end + else + require "iconv" + + def sh(command) + output = nil + IO.popen(command) { |f| output = f.read } + + if @encoding + Iconv.new('UTF-8', @encoding).iconv(output) + else + output + end + end + end + + if ExecJS.windows? + def shell_escape(*args) + # see http://technet.microsoft.com/en-us/library/cc723564.aspx#XSLTsection123121120120 + args.map { |arg| + arg = %Q("#{arg.gsub('"','""')}") if arg.match(/[&|()<>^ "]/) + arg + }.join(" ") + end + else + def shell_escape(*args) + Shellwords.join(args) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/johnson_runtime.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/johnson_runtime.rb new file mode 100644 index 0000000..44a9dae --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/johnson_runtime.rb @@ -0,0 +1,112 @@ +module ExecJS + class JohnsonRuntime + class Context + def initialize(source = "") + @runtime = Johnson::Runtime.new + @runtime.evaluate(source) + end + + def exec(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + eval "(function(){#{source}})()", options + end + end + + def eval(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + unbox @runtime.evaluate("(#{source})") + end + rescue Johnson::Error => e + if syntax_error?(e) + raise RuntimeError, e.message + else + raise ProgramError, e.message + end + end + + def call(properties, *args) + unbox @runtime.evaluate(properties).call(*args) + rescue Johnson::Error => e + if syntax_error?(e) + raise RuntimeError, e.message + else + raise ProgramError, e.message + end + end + + def unbox(value) + case + when function?(value) + nil + when string?(value) + value.respond_to?(:force_encoding) ? + value.force_encoding('UTF-8') : + value + when array?(value) + value.map { |v| unbox(v) } + when object?(value) + value.inject({}) do |vs, (k, v)| + vs[k] = unbox(v) unless function?(v) + vs + end + else + value + end + end + + private + def syntax_error?(error) + error.message =~ /^syntax error at / + end + + def function?(value) + value.respond_to?(:function?) && value.function? + end + + def string?(value) + value.is_a?(String) + end + + def array?(value) + array_test.call(value) + end + + def object?(value) + value.respond_to?(:inject) + end + + def array_test + @array_test ||= @runtime.evaluate("(function(a) {return a instanceof [].constructor})") + end + end + + def name + "Johnson (SpiderMonkey)" + end + + def exec(source) + context = Context.new + context.exec(source) + end + + def eval(source) + context = Context.new + context.eval(source) + end + + def compile(source) + Context.new(source) + end + + def available? + require "johnson" + true + rescue LoadError + false + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/module.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/module.rb new file mode 100644 index 0000000..6d155af --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/module.rb @@ -0,0 +1,38 @@ +require "execjs/version" +require "rbconfig" + +module ExecJS + class Error < ::StandardError; end + class RuntimeError < Error; end + class ProgramError < Error; end + class RuntimeUnavailable < RuntimeError; end + + class << self + attr_reader :runtime + + def runtime=(runtime) + raise RuntimeUnavailable, "#{runtime.name} is unavailable on this system" unless runtime.available? + @runtime = runtime + end + + def exec(source) + runtime.exec(source) + end + + def eval(source) + runtime.eval(source) + end + + def compile(source) + runtime.compile(source) + end + + def root + @root ||= File.expand_path("..", __FILE__) + end + + def windows? + @windows ||= RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/mustang_runtime.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/mustang_runtime.rb new file mode 100644 index 0000000..bef85c3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/mustang_runtime.rb @@ -0,0 +1,84 @@ +module ExecJS + class MustangRuntime + class Context + def initialize(source = "") + source = source.encode('UTF-8') if source.respond_to?(:encode) + + @v8_context = ::Mustang::Context.new + @v8_context.eval(source) + end + + def exec(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + eval "(function(){#{source}})()", options + end + end + + def eval(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + unbox @v8_context.eval("(#{source})") + end + end + + def call(properties, *args) + unbox @v8_context.eval(properties).call(*args) + rescue NoMethodError => e + raise ProgramError, e.message + end + + def unbox(value) + case value + when Mustang::V8::Array + value.map { |v| unbox(v) } + when Mustang::V8::Boolean + value.to_bool + when Mustang::V8::NullClass, Mustang::V8::UndefinedClass + nil + when Mustang::V8::Function + nil + when Mustang::V8::SyntaxError + raise RuntimeError, value.message + when Mustang::V8::Error + raise ProgramError, value.message + when Mustang::V8::Object + value.inject({}) { |h, (k, v)| + v = unbox(v) + h[k] = v if v + h + } + else + value.respond_to?(:delegate) ? value.delegate : value + end + end + end + + def name + "Mustang (V8)" + end + + def exec(source) + context = Context.new + context.exec(source) + end + + def eval(source) + context = Context.new + context.eval(source) + end + + def compile(source) + Context.new(source) + end + + def available? + require "mustang" + true + rescue LoadError + false + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/ruby_racer_runtime.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/ruby_racer_runtime.rb new file mode 100644 index 0000000..31d4703 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/ruby_racer_runtime.rb @@ -0,0 +1,117 @@ +module ExecJS + class RubyRacerRuntime + class Context + def initialize(source = "") + source = source.encode('UTF-8') if source.respond_to?(:encode) + + lock do + @v8_context = ::V8::Context.new + @v8_context.eval(source) + end + end + + def exec(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + eval "(function(){#{source}})()", options + end + end + + def eval(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + lock do + begin + unbox @v8_context.eval("(#{source})") + rescue ::V8::JSError => e + if e.value["name"] == "SyntaxError" + raise RuntimeError, e.message + else + raise ProgramError, e.message + end + end + end + end + end + + def call(properties, *args) + lock do + begin + unbox @v8_context.eval(properties).call(*args) + rescue ::V8::JSError => e + if e.value["name"] == "SyntaxError" + raise RuntimeError, e.message + else + raise ProgramError, e.message + end + end + end + end + + def unbox(value) + case value + when ::V8::Function + nil + when ::V8::Array + value.map { |v| unbox(v) } + when ::V8::Object + value.inject({}) do |vs, (k, v)| + vs[k] = unbox(v) unless v.is_a?(::V8::Function) + vs + end + when String + value.respond_to?(:force_encoding) ? + value.force_encoding('UTF-8') : + value + else + value + end + end + + private + def lock + result, exception = nil, nil + V8::C::Locker() do + begin + result = yield + rescue Exception => e + exception = e + end + end + + if exception + raise exception + else + result + end + end + end + + def name + "therubyracer (V8)" + end + + def exec(source) + context = Context.new + context.exec(source) + end + + def eval(source) + context = Context.new + context.eval(source) + end + + def compile(source) + Context.new(source) + end + + def available? + require "v8" + true + rescue LoadError + false + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/ruby_rhino_runtime.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/ruby_rhino_runtime.rb new file mode 100644 index 0000000..e6d5f8a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/ruby_rhino_runtime.rb @@ -0,0 +1,101 @@ +module ExecJS + class RubyRhinoRuntime + class Context + def initialize(source = "") + source = source.encode('UTF-8') if source.respond_to?(:encode) + + @rhino_context = ::Rhino::Context.new + fix_memory_limit! @rhino_context + @rhino_context.eval(source) + end + + def exec(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + eval "(function(){#{source}})()", options + end + end + + def eval(source, options = {}) + source = source.encode('UTF-8') if source.respond_to?(:encode) + + if /\S/ =~ source + unbox @rhino_context.eval("(#{source})") + end + rescue ::Rhino::JavascriptError => e + if e.message == "syntax error" + raise RuntimeError, e.message + else + raise ProgramError, e.message + end + end + + def call(properties, *args) + unbox @rhino_context.eval(properties).call(*args) + rescue ::Rhino::JavascriptError => e + if e.message == "syntax error" + raise RuntimeError, e.message + else + raise ProgramError, e.message + end + end + + def unbox(value) + case value = ::Rhino::To.ruby(value) + when ::Rhino::NativeFunction + nil + when ::Rhino::NativeObject + value.inject({}) do |vs, (k, v)| + case v + when ::Rhino::NativeFunction, ::Rhino::J::Function + nil + else + vs[k] = unbox(v) + end + vs + end + when Array + value.map { |v| unbox(v) } + else + value + end + end + + private + # Disables bytecode compiling which limits you to 64K scripts + def fix_memory_limit!(context) + if context.respond_to?(:optimization_level=) + context.optimization_level = -1 + else + context.instance_eval { @native.setOptimizationLevel(-1) } + end + end + end + + def name + "therubyrhino (Rhino)" + end + + def exec(source) + context = Context.new + context.exec(source) + end + + def eval(source) + context = Context.new + context.eval(source) + end + + def compile(source) + Context.new(source) + end + + def available? + require "rhino" + true + rescue LoadError + false + end + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/runtimes.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/runtimes.rb new file mode 100644 index 0000000..cb4d837 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/runtimes.rb @@ -0,0 +1,93 @@ +require "execjs/module" +require "execjs/disabled_runtime" +require "execjs/external_runtime" +require "execjs/johnson_runtime" +require "execjs/mustang_runtime" +require "execjs/ruby_racer_runtime" +require "execjs/ruby_rhino_runtime" + +module ExecJS + module Runtimes + Disabled = DisabledRuntime.new + + RubyRacer = RubyRacerRuntime.new + + RubyRhino = RubyRhinoRuntime.new + + Johnson = JohnsonRuntime.new + + Mustang = MustangRuntime.new + + Node = ExternalRuntime.new( + :name => "Node.js (V8)", + :command => ["nodejs", "node"], + :runner_path => ExecJS.root + "/support/node_runner.js", + :encoding => 'UTF-8' + ) + + JavaScriptCore = ExternalRuntime.new( + :name => "JavaScriptCore", + :command => "/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc", + :runner_path => ExecJS.root + "/support/jsc_runner.js" + ) + + SpiderMonkey = Spidermonkey = ExternalRuntime.new( + :name => "SpiderMonkey", + :command => "js", + :runner_path => ExecJS.root + "/support/spidermonkey_runner.js" + ) + + JScript = ExternalRuntime.new( + :name => "JScript", + :command => "cscript //E:jscript //Nologo //U", + :runner_path => ExecJS.root + "/support/jscript_runner.js", + :encoding => 'UTF-16LE' # CScript with //U returns UTF-16LE + ) + + + def self.autodetect + from_environment || best_available || + raise(RuntimeUnavailable, "Could not find a JavaScript runtime. " + + "See https://github.com/sstephenson/execjs for a list of available runtimes.") + end + + def self.best_available + runtimes.find(&:available?) + end + + def self.from_environment + if name = ENV["EXECJS_RUNTIME"] + if runtime = const_get(name) + if runtime.available? + runtime if runtime.available? + else + raise RuntimeUnavailable, "#{runtime.name} runtime is not available on this system" + end + elsif !name.empty? + raise RuntimeUnavailable, "#{name} runtime is not defined" + end + end + end + + def self.names + @names ||= constants.inject({}) { |h, name| h.merge(const_get(name) => name) }.values + end + + def self.runtimes + @runtimes ||= [ + RubyRacer, + RubyRhino, + Johnson, + Mustang, + Node, + JavaScriptCore, + SpiderMonkey, + JScript + ] + end + end + + def self.runtimes + Runtimes.runtimes + end +end diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/jsc_runner.js b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/jsc_runner.js new file mode 100644 index 0000000..a88a024 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/jsc_runner.js @@ -0,0 +1,19 @@ +(function(program, execJS) { execJS(program) })(function() { + return eval(#{encoded_source}); +}, function(program) { + var output; + try { + result = program(); + if (typeof result == 'undefined' && result !== null) { + print('["ok"]'); + } else { + try { + print(JSON.stringify(['ok', result])); + } catch (err) { + print('["err"]'); + } + } + } catch (err) { + print(JSON.stringify(['err', '' + err])); + } +}); diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/jscript_runner.js b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/jscript_runner.js new file mode 100644 index 0000000..d27edf1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/jscript_runner.js @@ -0,0 +1,22 @@ +(function(program, execJS) { execJS(program) })(function() { + return eval(#{encoded_source}); +}, function(program) { + #{json2_source} + var output, print = function(string) { + WScript.Echo(string); + }; + try { + result = program(); + if (typeof result == 'undefined' && result !== null) { + print('["ok"]'); + } else { + try { + print(JSON.stringify(['ok', result])); + } catch (err) { + print('["err"]'); + } + } + } catch (err) { + print(JSON.stringify(['err', err.name + ': ' + err.message])); + } +}); diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/json2.js b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/json2.js new file mode 100644 index 0000000..fb8fe0a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/json2.js @@ -0,0 +1,481 @@ +/* + http://www.JSON.org/json2.js + 2011-01-18 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +(function (global) { + if (!global.JSON) { + global.JSON = {}; + } + + var JSON = global.JSON; + + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}(this)); diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/node_runner.js b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/node_runner.js new file mode 100644 index 0000000..f4d3b77 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/node_runner.js @@ -0,0 +1,20 @@ +(function(program, execJS) { execJS(program) })(function(module, exports, require) { #{source} +}, function(program) { + var output, print = function(string) { + process.stdout.write('' + string); + }; + try { + result = program(); + if (typeof result == 'undefined' && result !== null) { + print('["ok"]'); + } else { + try { + print(JSON.stringify(['ok', result])); + } catch (err) { + print('["err"]'); + } + } + } catch (err) { + print(JSON.stringify(['err', '' + err])); + } +}); diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/spidermonkey_runner.js b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/spidermonkey_runner.js new file mode 100644 index 0000000..d774c9a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/support/spidermonkey_runner.js @@ -0,0 +1,19 @@ +(function(program, execJS) { execJS(program) })(function() { #{source} +}, function(program) { + #{json2_source} + var output; + try { + result = program(); + if (typeof result == 'undefined' && result !== null) { + print('["ok"]'); + } else { + try { + print(JSON.stringify(['ok', result])); + } catch (err) { + print('["err"]'); + } + } + } catch (err) { + print(JSON.stringify(['err', '' + err])); + } +}); diff --git a/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/version.rb b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/version.rb new file mode 100644 index 0000000..493dbfa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/execjs-1.3.0/lib/execjs/version.rb @@ -0,0 +1,3 @@ +module ExecJS + VERSION = "1.3.0" +end diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/.gitignore b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/.gitignore new file mode 100644 index 0000000..d04d974 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/.gitignore @@ -0,0 +1,2 @@ +.bundle +Gemfile.lock diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/Gemfile b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/Gemfile new file mode 100644 index 0000000..66fc1d3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/Gemfile @@ -0,0 +1,13 @@ +source :rubygems + +gemspec + +gem "rails", "~> 3.0.3" + +if RUBY_VERSION < "1.9" + gem "ruby-debug" +else + gem "test-unit" +end + +gem "mocha" \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/MIT-LICENSE b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/MIT-LICENSE new file mode 100644 index 0000000..6c8f9b3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/README.rdoc b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/README.rdoc new file mode 100644 index 0000000..d4bcbc1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/README.rdoc @@ -0,0 +1,101 @@ +== HasScope + +Has scope allows you to easily create controller filters based on your resources named scopes. +Imagine the following model called graduations: + + class Graduation < ActiveRecord::Base + named_scope :featured, :conditions => { :featured => true } + named_scope :by_degree, proc {|degree| { :conditions => { :degree => degree } } } + end + +You can use those named scopes as filters by declaring them on your controller: + + class GraduationsController < ApplicationController + has_scope :featured, :type => :boolean + has_scope :by_degree + end + +Now, if you want to apply them to an specific resource, you just need to call apply_scopes: + + class GraduationsController < ApplicationController + has_scope :featured, :type => :boolean + has_scope :by_degree + has_scope :by_period, :using => [:started_at, :ended_at] + + def index + @graduations = apply_scopes(Graduation).all + end + end + +Then for each request: + + /graduations + #=> acts like a normal request + + /graduations?featured=true + #=> calls the named scope and bring featured graduations + + /graduations?params[by_period][started_at]=20100701¶ms[by_period][ended_at]=20101013 + #=> brings graduations in the given period + + /graduations?featured=true&by_degree=phd + #=> brings featured graduations with phd degree + +You can retrieve all the scopes applied in one action with current_scopes method. +In the last case, it would return: { :featured => true, :by_degree => "phd" }. + +== Installation + +HasScope is available as gem on Gemcutter, so just run the following: + + sudo gem install has_scope + +If you want it as plugin, just do: + + script/plugin install git://github.com/plataformatec/has_scope.git + +== Options + +HasScope supports several options: + +* :type - Checks the type of the parameter sent. If set to :boolean it just calls the named scope, without any argument. By default, it does not allow hashes or arrays to be given, except if type :hash or :array are set. + +* :only - In which actions the scope is applied. + +* :except - In which actions the scope is not applied. + +* :as - The key in the params hash expected to find the scope. Defaults to the scope name. + +* :using - The subkeys to be used as args when type is a hash. + +* :if - Specifies a method, proc or string to call to determine if the scope should apply. + +* :unless - Specifies a method, proc or string to call to determine if the scope should NOT apply. + +* :default - Default value for the scope. Whenever supplied the scope is always called. + +* :allow_blank - Blank values are not sent to scopes by default. Set to true to overwrite. + +== Block usage + +has_scope also accepts a block. The controller, current scope and value are yielded +to the block so the user can apply the scope on its own. This is useful in case we +need to manipulate the given value: + + has_scope :category do |controller, scope, value| + value != "all" ? scope.by_category(value) : scope + end + +When used with booleans, it just receives two arguments and is just invoked if true is given: + + has_scope :not_voted_by_me, :type => :boolean do |controller, scope| + scope.not_voted_by(controller.current_user.id) + end + +== Bugs and Feedback + +If you discover any bugs or want to drop a line, feel free to create an issue on GitHub. + +http://github.com/plataformatec/has_scope/issues + +MIT License. Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/Rakefile b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/Rakefile new file mode 100644 index 0000000..c21c228 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/Rakefile @@ -0,0 +1,24 @@ +# encoding: UTF-8 +require 'rake' +require 'rake/testtask' +require 'rdoc/task' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test HasScope' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for HasScope' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'HasScope' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/*.rb') +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/has_scope.gemspec b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/has_scope.gemspec new file mode 100644 index 0000000..afa3cb7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/has_scope.gemspec @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "has_scope/version" + +Gem::Specification.new do |s| + s.name = "has_scope" + s.version = HasScope::VERSION.dup + s.platform = Gem::Platform::RUBY + s.summary = "Maps controller filters to your resource scopes." + s.email = "developers@plataformatec.com.br" + s.homepage = "http://github.com/plataformatec/has_scope" + s.description = "Maps controller filters to your resource scopes" + s.authors = ['José Valim'] + + s.rubyforge_project = "has_scope" + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] + + s.rdoc_options = ["--charset=UTF-8"] + s.extra_rdoc_files = [ + "README.rdoc" + ] +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/init.rb b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/init.rb new file mode 100644 index 0000000..5016ca7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/init.rb @@ -0,0 +1 @@ +require 'has_scope' diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/lib/has_scope.rb b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/lib/has_scope.rb new file mode 100644 index 0000000..53673b1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/lib/has_scope.rb @@ -0,0 +1,187 @@ +module HasScope + TRUE_VALUES = ["true", true, "1", 1] + + ALLOWED_TYPES = { + :array => [ Array ], + :hash => [ Hash ], + :boolean => [ Object ], + :default => [ String, Numeric ] + } + + def self.included(base) + base.class_eval do + extend ClassMethods + helper_method :current_scopes + class_attribute :scopes_configuration, :instance_writer => false + end + end + + module ClassMethods + # Detects params from url and apply as scopes to your classes. + # + # == Options + # + # * :type - Checks the type of the parameter sent. If set to :boolean + # it just calls the named scope, without any argument. By default, + # it does not allow hashes or arrays to be given, except if type + # :hash or :array are set. + # + # * :only - In which actions the scope is applied. By default is :all. + # + # * :except - In which actions the scope is not applied. By default is :none. + # + # * :as - The key in the params hash expected to find the scope. + # Defaults to the scope name. + # + # * :using - If type is a hash, you can provide :using to convert the hash to + # a named scope call with several arguments. + # + # * :if - Specifies a method, proc or string to call to determine + # if the scope should apply + # + # * :unless - Specifies a method, proc or string to call to determine + # if the scope should NOT apply. + # + # * :default - Default value for the scope. Whenever supplied the scope + # is always called. + # + # * :allow_blank - Blank values are not sent to scopes by default. Set to true to overwrite. + # + # == Block usage + # + # has_scope also accepts a block. The controller, current scope and value are yielded + # to the block so the user can apply the scope on its own. This is useful in case we + # need to manipulate the given value: + # + # has_scope :category do |controller, scope, value| + # value != "all" ? scope.by_category(value) : scope + # end + # + # has_scope :not_voted_by_me, :type => :boolean do |controller, scope| + # scope.not_voted_by(controller.current_user.id) + # end + # + def has_scope(*scopes, &block) + options = scopes.extract_options! + options.symbolize_keys! + options.assert_valid_keys(:type, :only, :except, :if, :unless, :default, :as, :using, :allow_blank) + + if options.key?(:using) + if options.key?(:type) && options[:type] != :hash + raise "You cannot use :using with another :type different than :hash" + else + options[:type] = :hash + end + + options[:using] = Array(options[:using]) + end + + options[:only] = Array(options[:only]) + options[:except] = Array(options[:except]) + + self.scopes_configuration = (self.scopes_configuration || {}).dup + + scopes.each do |scope| + self.scopes_configuration[scope] ||= { :as => scope, :type => :default, :block => block } + self.scopes_configuration[scope] = self.scopes_configuration[scope].merge(options) + end + end + end + + protected + + # Receives an object where scopes will be applied to. + # + # class GraduationsController < InheritedResources::Base + # has_scope :featured, :type => true, :only => :index + # has_scope :by_degree, :only => :index + # + # def index + # @graduations = apply_scopes(Graduation).all + # end + # end + # + def apply_scopes(target, hash=params) + return target unless scopes_configuration + + self.scopes_configuration.each do |scope, options| + next unless apply_scope_to_action?(options) + key = options[:as] + + if hash.key?(key) + value, call_scope = hash[key], true + elsif options.key?(:default) + value, call_scope = options[:default], true + value = value.call(self) if value.is_a?(Proc) + end + + value = parse_value(options[:type], key, value) + + if call_scope && (value.present? || options[:allow_blank]) + current_scopes[key] = value + target = call_scope_by_type(options[:type], scope, target, value, options) + end + end + + target + end + + # Set the real value for the current scope if type check. + def parse_value(type, key, value) #:nodoc: + if type == :boolean + TRUE_VALUES.include?(value) + elsif value && ALLOWED_TYPES[type].none?{ |klass| value.is_a?(klass) } + raise "Expected type :#{type} in params[:#{key}], got #{value.class}" + else + value + end + end + + # Call the scope taking into account its type. + def call_scope_by_type(type, scope, target, value, options) #:nodoc: + block = options[:block] + + if type == :boolean + block ? block.call(self, target) : target.send(scope) + elsif value && options.key?(:using) + value = value.values_at(*options[:using]) + block ? block.call(self, target, value) : target.send(scope, *value) + else + block ? block.call(self, target, value) : target.send(scope, value) + end + end + + # Given an options with :only and :except arrays, check if the scope + # can be performed in the current action. + def apply_scope_to_action?(options) #:nodoc: + return false unless applicable?(options[:if], true) && applicable?(options[:unless], false) + + if options[:only].empty? + options[:except].empty? || !options[:except].include?(action_name.to_sym) + else + options[:only].include?(action_name.to_sym) + end + end + + # Evaluates the scope options :if or :unless. Returns true if the proc + # method, or string evals to the expected value. + def applicable?(string_proc_or_symbol, expected) #:nodoc: + case string_proc_or_symbol + when String + eval(string_proc_or_symbol) == expected + when Proc + string_proc_or_symbol.call(self) == expected + when Symbol + send(string_proc_or_symbol) == expected + else + true + end + end + + # Returns the scopes used in this action. + def current_scopes + @current_scopes ||= {} + end +end + +ActionController::Base.send :include, HasScope diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/lib/has_scope/version.rb b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/lib/has_scope/version.rb new file mode 100644 index 0000000..76f3304 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/lib/has_scope/version.rb @@ -0,0 +1,3 @@ +module HasScope + VERSION = "0.5.1" +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/test/has_scope_test.rb b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/test/has_scope_test.rb new file mode 100644 index 0000000..2a9aec7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/test/has_scope_test.rb @@ -0,0 +1,249 @@ +require 'test_helper' + +class Tree +end + +class TreesController < ApplicationController + has_scope :color, :unless => :show_all_colors? + has_scope :only_tall, :type => :boolean, :only => :index, :if => :restrict_to_only_tall_trees? + has_scope :shadown_range, :default => 10, :except => [ :index, :show, :new ] + has_scope :root_type, :as => :root, :allow_blank => true + has_scope :calculate_height, :default => proc {|c| c.session[:height] || 20 }, :only => :new + has_scope :paginate, :type => :hash + has_scope :args_paginate, :type => :hash, :using => [:page, :per_page] + has_scope :categories, :type => :array + + has_scope :only_short, :type => :boolean do |controller, scope| + scope.only_really_short!(controller.object_id) + end + + has_scope :by_category do |controller, scope, value| + scope.by_given_category(controller.object_id, value + "_id") + end + + def index + @trees = apply_scopes(Tree).all + end + + def new + @tree = apply_scopes(Tree).new + end + + def show + @tree = apply_scopes(Tree).find(params[:id]) + end + alias :edit :show + + protected + def restrict_to_only_tall_trees? + true + end + + def show_all_colors? + false + end + + def default_render + render :text => action_name + end +end + +class BonsaisController < TreesController + has_scope :categories, :if => :categories? + + protected + def categories? + false + end +end + +class HasScopeTest < ActionController::TestCase + tests TreesController + + def test_boolean_scope_is_called_when_boolean_param_is_true + Tree.expects(:only_tall).with().returns(Tree).in_sequence + Tree.expects(:all).returns([mock_tree]).in_sequence + get :index, :only_tall => 'true' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :only_tall => true }, current_scopes) + end + + def test_boolean_scope_is_not_called_when_boolean_param_is_false + Tree.expects(:only_tall).never + Tree.expects(:all).returns([mock_tree]) + get :index, :only_tall => 'false' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({}, current_scopes) + end + + def test_scope_is_called_only_on_index + Tree.expects(:only_tall).never + Tree.expects(:find).with('42').returns(mock_tree) + get :show, :only_tall => 'true', :id => '42' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ }, current_scopes) + end + + def test_scope_is_skipped_when_if_option_is_false + @controller.stubs(:restrict_to_only_tall_trees?).returns(false) + Tree.expects(:only_tall).never + Tree.expects(:all).returns([mock_tree]) + get :index, :only_tall => 'true' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ }, current_scopes) + end + + def test_scope_is_skipped_when_unless_option_is_true + @controller.stubs(:show_all_colors?).returns(true) + Tree.expects(:color).never + Tree.expects(:all).returns([mock_tree]) + get :index, :color => 'blue' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ }, current_scopes) + end + + def test_scope_is_called_except_on_index + Tree.expects(:shadown_range).with().never + Tree.expects(:all).returns([mock_tree]) + get :index, :shadown_range => 20 + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ }, current_scopes) + end + + def test_scope_is_called_with_arguments + Tree.expects(:color).with('blue').returns(Tree).in_sequence + Tree.expects(:all).returns([mock_tree]).in_sequence + get :index, :color => 'blue' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :color => 'blue' }, current_scopes) + end + + def test_scope_is_not_called_if_blank + Tree.expects(:color).never + Tree.expects(:all).returns([mock_tree]).in_sequence + get :index, :color => '' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ }, current_scopes) + end + + def test_scope_is_called_when_blank_if_allow_blank_is_given + Tree.expects(:root_type).with('').returns(Tree) + Tree.expects(:all).returns([mock_tree]).in_sequence + get :index, :root => '' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :root => '' }, current_scopes) + end + + def test_multiple_scopes_are_called + Tree.expects(:only_tall).with().returns(Tree) + Tree.expects(:color).with('blue').returns(Tree) + Tree.expects(:all).returns([mock_tree]) + get :index, :color => 'blue', :only_tall => 'true' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :color => 'blue', :only_tall => true }, current_scopes) + end + + def test_scope_of_type_hash + hash = { "page" => "1", "per_page" => "10" } + Tree.expects(:paginate).with(hash).returns(Tree) + Tree.expects(:all).returns([mock_tree]) + get :index, :paginate => hash + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :paginate => hash }, current_scopes) + end + + def test_scope_of_type_hash_with_using + hash = { "page" => "1", "per_page" => "10" } + Tree.expects(:args_paginate).with("1", "10").returns(Tree) + Tree.expects(:all).returns([mock_tree]) + get :index, :args_paginate => hash + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :args_paginate => hash }, current_scopes) + end + + def test_scope_of_type_array + array = %w(book kitchen sport) + Tree.expects(:categories).with(array).returns(Tree) + Tree.expects(:all).returns([mock_tree]) + get :index, :categories => array + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :categories => array }, current_scopes) + end + + def test_invalid_type_hash_for_default_type_scope + assert_raise RuntimeError do + get :index, :color => { :blue => :red } + end + end + + def test_invalid_type_string_for_hash_type_scope + assert_raise RuntimeError do + get :index, :paginate => "1" + end + end + + def test_scope_is_called_with_default_value + Tree.expects(:shadown_range).with(10).returns(Tree).in_sequence + Tree.expects(:find).with('42').returns(mock_tree).in_sequence + get :edit, :id => '42' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :shadown_range => 10 }, current_scopes) + end + + def test_default_scope_value_can_be_overwritten + Tree.expects(:shadown_range).with('20').returns(Tree).in_sequence + Tree.expects(:find).with('42').returns(mock_tree).in_sequence + get :edit, :id => '42', :shadown_range => '20' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :shadown_range => '20' }, current_scopes) + end + + def test_scope_with_different_key + Tree.expects(:root_type).with('outside').returns(Tree).in_sequence + Tree.expects(:find).with('42').returns(mock_tree).in_sequence + get :show, :id => '42', :root => 'outside' + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :root => 'outside' }, current_scopes) + end + + def test_scope_with_default_value_as_proc + session[:height] = 100 + Tree.expects(:calculate_height).with(100).returns(Tree).in_sequence + Tree.expects(:new).returns(mock_tree).in_sequence + get :new + assert_equal(mock_tree, assigns(:tree)) + assert_equal({ :calculate_height => 100 }, current_scopes) + end + + def test_scope_with_boolean_block + Tree.expects(:only_really_short!).with(@controller.object_id).returns(Tree) + Tree.expects(:all).returns([mock_tree]) + get :index, :only_short => 'true' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :only_short => true }, current_scopes) + end + + def test_scope_with_other_block_types + Tree.expects(:by_given_category).with(@controller.object_id, 'for_id').returns(Tree) + Tree.expects(:all).returns([mock_tree]) + get :index, :by_category => 'for' + assert_equal([mock_tree], assigns(:trees)) + assert_equal({ :by_category => 'for' }, current_scopes) + end + + def test_overwritten_scope + assert_nil(TreesController.scopes_configuration[:categories][:if]) + assert_equal(:categories?, BonsaisController.scopes_configuration[:categories][:if]) + end + + protected + + def mock_tree(stubs={}) + @mock_tree ||= mock(stubs) + end + + def current_scopes + @controller.send :current_scopes + end +end + diff --git a/vendor/ruby/1.9.1/gems/has_scope-0.5.1/test/test_helper.rb b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/test/test_helper.rb new file mode 100644 index 0000000..c68a3c4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/has_scope-0.5.1/test/test_helper.rb @@ -0,0 +1,31 @@ +require 'rubygems' +require 'bundler' + +Bundler.setup +require 'test/unit' +require 'mocha' + +# Configure Rails +ENV["RAILS_ENV"] = "test" + +require 'active_support' +require 'action_controller' +require 'action_dispatch/middleware/flash' + +$:.unshift File.expand_path('../../lib', __FILE__) +require 'has_scope' + +HasScope::Routes = ActionDispatch::Routing::RouteSet.new +HasScope::Routes.draw do + match '/:controller(/:action(/:id))' +end + +class ApplicationController < ActionController::Base + include HasScope::Routes.url_helpers +end + +class ActiveSupport::TestCase + setup do + @routes = HasScope::Routes + end +end diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/LICENSE b/vendor/ruby/1.9.1/gems/hike-1.2.1/LICENSE new file mode 100644 index 0000000..63c11cb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011 Sam Stephenson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/README.md b/vendor/ruby/1.9.1/gems/hike-1.2.1/README.md new file mode 100644 index 0000000..f2c2f24 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/README.md @@ -0,0 +1,52 @@ +Hike +==== + +Hike is a Ruby library for finding files in a set of paths. Use it to +implement search paths, load paths, and the like. + +# Examples + +Find Ruby files in this project: + + trail = Hike::Trail.new "/Users/sam/Projects/hike" + trail.append_extension ".rb" + trail.append_paths "lib", "test" + + trail.find "hike/trail" + # => "/Users/sam/Projects/hike/lib/hike/trail.rb" + + trail.find "test_trail" + # => "/Users/sam/Projects/hike/test/test_trail.rb" + +Explore your Ruby load path: + + trail = Hike::Trail.new "/" + trail.append_extensions ".rb", ".bundle" + trail.append_paths *$: + + trail.find "net/http" + # => "/Users/sam/.rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/net/http.rb" + + trail.find "strscan" + # => "/Users/sam/.rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/i686-darwin10.4.0/strscan.bundle" + +Explore your shell path: + + trail = Hike::Trail.new "/" + trail.append_paths *ENV["PATH"].split(":") + + trail.find "ls" + # => "/bin/ls" + + trail.find "gem" + # => "/Users/sam/.rvm/rubies/ree-1.8.7-2010.02/bin/gem" + +# Installation + + $ gem install hike + +# License + +Copyright (c) 2011 Sam Stephenson. + +Released under the MIT license. See `LICENSE` for details. diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike.rb b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike.rb new file mode 100644 index 0000000..48d46e8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike.rb @@ -0,0 +1,9 @@ +module Hike + VERSION = "1.2.0" + + autoload :Extensions, "hike/extensions" + autoload :Index, "hike/index" + autoload :NormalizedArray, "hike/normalized_array" + autoload :Paths, "hike/paths" + autoload :Trail, "hike/trail" +end diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/extensions.rb b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/extensions.rb new file mode 100644 index 0000000..f32bfd8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/extensions.rb @@ -0,0 +1,23 @@ +require 'hike/normalized_array' + +module Hike + # `Extensions` is an internal collection for tracking extension names. + class Extensions < NormalizedArray + # Extensions added to this array are normalized with a leading + # `.`. + # + # extensions << "js" + # extensions << ".css" + # + # extensions + # # => [".js", ".css"] + # + def normalize_element(extension) + if extension[/^\./] + extension + else + ".#{extension}" + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/index.rb b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/index.rb new file mode 100644 index 0000000..c5f2e00 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/index.rb @@ -0,0 +1,204 @@ +require 'pathname' + +module Hike + # `Index` is an internal cached variant of `Trail`. It assumes the + # file system does not change between `find` calls. All `stat` and + # `entries` calls are cached for the lifetime of the `Index` object. + class Index + # `Index#paths` is an immutable `Paths` collection. + attr_reader :paths + + # `Index#extensions` is an immutable `Extensions` collection. + attr_reader :extensions + + # `Index#aliases` is an immutable `Hash` mapping an extension to + # an `Array` of aliases. + attr_reader :aliases + + # `Index.new` is an internal method. Instead of constructing it + # directly, create a `Trail` and call `Trail#index`. + def initialize(root, paths, extensions, aliases) + @root = root + + # Freeze is used here so an error is throw if a mutator method + # is called on the array. Mutating `@paths`, `@extensions`, or + # `@aliases` would have unpredictable results. + @paths = paths.dup.freeze + @extensions = extensions.dup.freeze + @aliases = aliases.inject({}) { |h, (k, a)| + h[k] = a.dup.freeze; h + }.freeze + @pathnames = paths.map { |path| Pathname.new(path) } + + @stats = {} + @entries = {} + @patterns = {} + end + + # `Index#root` returns root path as a `String`. This attribute is immutable. + def root + @root.to_s + end + + # `Index#index` returns `self` to be compatable with the `Trail` interface. + def index + self + end + + # The real implementation of `find`. `Trail#find` generates a one + # time index and delegates here. + # + # See `Trail#find` for usage. + def find(*logical_paths, &block) + if block_given? + options = extract_options!(logical_paths) + base_path = Pathname.new(options[:base_path] || @root) + + logical_paths.each do |logical_path| + logical_path = Pathname.new(logical_path.sub(/^\//, '')) + + if relative?(logical_path) + find_in_base_path(logical_path, base_path, &block) + else + find_in_paths(logical_path, &block) + end + end + + nil + else + find(*logical_paths) do |path| + return path + end + end + end + + # A cached version of `Dir.entries` that filters out `.` files and + # `~` swap files. Returns an empty `Array` if the directory does + # not exist. + def entries(path) + key = path.to_s + @entries[key] ||= Pathname.new(path).entries.reject { |entry| entry.to_s =~ /^\.|~$|^\#.*\#$/ }.sort + rescue Errno::ENOENT + @entries[key] = [] + end + + # A cached version of `File.stat`. Returns nil if the file does + # not exist. + def stat(path) + key = path.to_s + if @stats.key?(key) + @stats[key] + else + begin + @stats[key] = File.stat(path) + rescue Errno::ENOENT + @stats[key] = nil + end + end + end + + protected + def extract_options!(arguments) + arguments.last.is_a?(Hash) ? arguments.pop.dup : {} + end + + def relative?(logical_path) + logical_path.to_s =~ /^\.\.?\// + end + + # Finds logical path across all `paths` + def find_in_paths(logical_path, &block) + dirname, basename = logical_path.split + @pathnames.each do |base_path| + match(base_path.join(dirname), basename, &block) + end + end + + # Finds relative logical path, `../test/test_trail`. Requires a + # `base_path` for reference. + def find_in_base_path(logical_path, base_path, &block) + candidate = base_path.join(logical_path) + dirname, basename = candidate.split + match(dirname, basename, &block) if paths_contain?(dirname) + end + + # Checks if the path is actually on the file system and performs + # any syscalls if necessary. + def match(dirname, basename) + # Potential `entries` syscall + matches = entries(dirname) + + pattern = pattern_for(basename) + matches = matches.select { |m| m.to_s =~ pattern } + + sort_matches(matches, basename).each do |path| + pathname = dirname.join(path) + + # Potential `stat` syscall + stat = stat(pathname) + + # Exclude directories + if stat && stat.file? + yield pathname.to_s + end + end + end + + # Returns true if `dirname` is a subdirectory of any of the `paths` + def paths_contain?(dirname) + paths.any? { |path| dirname.to_s[0, path.length] == path } + end + + # Cache results of `build_pattern_for` + def pattern_for(basename) + @patterns[basename] ||= build_pattern_for(basename) + end + + # Returns a `Regexp` that matches the allowed extensions. + # + # pattern_for("index.html") #=> /^index(.html|.htm)(.builder|.erb)*$/ + def build_pattern_for(basename) + extname = basename.extname + aliases = find_aliases_for(extname) + + if aliases.any? + basename = basename.basename(extname) + aliases = [extname] + aliases + aliases_pattern = aliases.map { |e| Regexp.escape(e) }.join("|") + basename_re = Regexp.escape(basename.to_s) + "(?:#{aliases_pattern})" + else + basename_re = Regexp.escape(basename.to_s) + end + + extension_pattern = extensions.map { |e| Regexp.escape(e) }.join("|") + /^#{basename_re}(?:#{extension_pattern})*$/ + end + + # Sorts candidate matches by their extension + # priority. Extensions in the front of the `extensions` carry + # more weight. + def sort_matches(matches, basename) + aliases = find_aliases_for(basename.extname) + + matches.sort_by do |match| + extnames = match.sub(basename.to_s, '').to_s.scan(/\.[^.]+/) + extnames.inject(0) do |sum, ext| + if i = extensions.index(ext) + sum + i + 1 + elsif i = aliases.index(ext) + sum + i + 11 + else + sum + end + end + end + end + + def find_aliases_for(extension) + @aliases.inject([]) do |aliases, (key, value)| + aliases.push(key) if value == extension + aliases + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/normalized_array.rb b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/normalized_array.rb new file mode 100644 index 0000000..3ba2d47 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/normalized_array.rb @@ -0,0 +1,59 @@ +module Hike + # `NormalizedArray` is an internal abstract wrapper class that calls + # a callback `normalize_element` anytime an element is added to the + # Array. + # + # `Extensions` and `Paths` are subclasses of `NormalizedArray`. + class NormalizedArray < Array + def initialize + super() + end + + def []=(*args) + value = args.pop + + if value.respond_to?(:to_ary) + value = normalize_elements(value) + else + value = normalize_element(value) + end + + super(*args.concat([value])) + end + + def <<(element) + super normalize_element(element) + end + + def collect! + super do |element| + result = yield element + normalize_element(result) + end + end + + alias_method :map!, :collect! + + def insert(index, *elements) + super index, *normalize_elements(elements) + end + + def push(*elements) + super(*normalize_elements(elements)) + end + + def replace(elements) + super normalize_elements(elements) + end + + def unshift(*elements) + super(*normalize_elements(elements)) + end + + def normalize_elements(elements) + elements.map do |element| + normalize_element(element) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/paths.rb b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/paths.rb new file mode 100644 index 0000000..0dad9ab --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/paths.rb @@ -0,0 +1,27 @@ +require 'pathname' +require 'hike/normalized_array' + +module Hike + # `Paths` is an internal collection for tracking path strings. + class Paths < NormalizedArray + def initialize(root = ".") + @root = Pathname.new(root) + super() + end + + # Relative paths added to this array are expanded relative to `@root`. + # + # paths = Paths.new("/usr/local") + # paths << "tmp" + # paths << "/tmp" + # + # paths + # # => ["/usr/local/tmp", "/tmp"] + # + def normalize_element(path) + path = Pathname.new(path) + path = @root.join(path) if path.relative? + path.expand_path.to_s + end + end +end diff --git a/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/trail.rb b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/trail.rb new file mode 100644 index 0000000..f0728b4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/hike-1.2.1/lib/hike/trail.rb @@ -0,0 +1,179 @@ +require 'pathname' +require 'hike/extensions' +require 'hike/index' +require 'hike/paths' + +module Hike + # `Trail` is the public container class for holding paths and extensions. + class Trail + # `Trail#paths` is a mutable `Paths` collection. + # + # trail = Hike::Trail.new + # trail.paths.push "~/Projects/hike/lib", "~/Projects/hike/test" + # + # The order of the paths is significant. Paths in the beginning of + # the collection will be checked first. In the example above, + # `~/Projects/hike/lib/hike.rb` would shadow the existent of + # `~/Projects/hike/test/hike.rb`. + attr_reader :paths + + # `Trail#extensions` is a mutable `Extensions` collection. + # + # trail = Hike::Trail.new + # trail.paths.push "~/Projects/hike/lib" + # trail.extensions.push ".rb" + # + # Extensions allow you to find files by just their name omitting + # their extension. Is similar to Ruby's require mechanism that + # allows you to require files with specifiying `foo.rb`. + attr_reader :extensions + + # `Index#aliases` is a mutable `Hash` mapping an extension to + # an `Array` of aliases. + # + # trail = Hike::Trail.new + # trail.paths.push "~/Projects/hike/site" + # trail.aliases['.htm'] = 'html' + # trail.aliases['.xhtml'] = 'html' + # trail.aliases['.php'] = 'html' + # + # Aliases provide a fallback when the primary extension is not + # matched. In the example above, a lookup for "foo.html" will + # check for the existence of "foo.htm", "foo.xhtml", or "foo.php". + attr_reader :aliases + + # A Trail accepts an optional root path that defaults to your + # current working directory. Any relative paths added to + # `Trail#paths` will expanded relative to the root. + def initialize(root = ".") + @root = Pathname.new(root).expand_path + @paths = Paths.new(@root) + @extensions = Extensions.new + @aliases = Hash.new { |h, k| h[k] = Extensions.new } + end + + # `Trail#root` returns root path as a `String`. This attribute is immutable. + def root + @root.to_s + end + + # Prepend `path` to `Paths` collection + def prepend_paths(*paths) + self.paths.unshift(*paths) + end + alias_method :prepend_path, :prepend_paths + + # Append `path` to `Paths` collection + def append_paths(*paths) + self.paths.push(*paths) + end + alias_method :append_path, :append_paths + + # Remove `path` from `Paths` collection + def remove_path(path) + self.paths.delete(path) + end + + # Prepend `extension` to `Extensions` collection + def prepend_extensions(*extensions) + self.extensions.unshift(*extensions) + end + alias_method :prepend_extension, :prepend_extensions + + # Append `extension` to `Extensions` collection + def append_extensions(*extensions) + self.extensions.push(*extensions) + end + alias_method :append_extension, :append_extensions + + # Remove `extension` from `Extensions` collection + def remove_extension(extension) + self.extensions.delete(extension) + end + + # Alias `new_extension` to `old_extension` + def alias_extension(new_extension, old_extension) + aliases[normalize_extension(new_extension)] = normalize_extension(old_extension) + end + + # Remove the alias for `extension` + def unalias_extension(extension) + aliases.delete(normalize_extension(extension)) + end + + # `Trail#find` returns a the expand path for a logical path in the + # path collection. + # + # trail = Hike::Trail.new "~/Projects/hike" + # trail.extensions.push ".rb" + # trail.paths.push "lib", "test" + # + # trail.find "hike/trail" + # # => "~/Projects/hike/lib/hike/trail.rb" + # + # trail.find "test_trail" + # # => "~/Projects/hike/test/test_trail.rb" + # + # `find` accepts multiple fallback logical paths that returns the + # first match. + # + # trail.find "hike", "hike/index" + # + # is equivalent to + # + # trail.find("hike") || trail.find("hike/index") + # + # Though `find` always returns the first match, it is possible + # to iterate over all shadowed matches and fallbacks by supplying + # a block. + # + # trail.find("hike", "hike/index") { |path| warn path } + # + # This allows you to filter your matches by any condition. + # + # trail.find("application") do |path| + # return path if mime_type_for(path) == "text/css" + # end + # + def find(*args, &block) + index.find(*args, &block) + end + + # `Trail#index` returns an `Index` object that has the same + # interface as `Trail`. An `Index` is a cached `Trail` object that + # does not update when the file system changes. If you are + # confident that you are not making changes the paths you are + # searching, `index` will avoid excess system calls. + # + # index = trail.index + # index.find "hike/trail" + # index.find "test_trail" + # + def index + Index.new(root, paths, extensions, aliases) + end + + # `Trail#entries` is equivalent to `Dir#entries`. It is not + # recommend to use this method for general purposes. It exists for + # parity with `Index#entries`. + def entries(*args) + index.entries(*args) + end + + # `Trail#stat` is equivalent to `File#stat`. It is not + # recommend to use this method for general purposes. It exists for + # parity with `Index#stat`. + def stat(*args) + index.stat(*args) + end + + private + def normalize_extension(extension) + if extension[/^\./] + extension + else + ".#{extension}" + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/CHANGELOG.textile b/vendor/ruby/1.9.1/gems/i18n-0.6.0/CHANGELOG.textile new file mode 100644 index 0000000..e1eeda8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/CHANGELOG.textile @@ -0,0 +1,152 @@ +h1. Changelog + +h2. 0.5.0 + +* "Extract Backend::ActiveRecord to a separate gem":https://github.com/svenfuchs/i18n/commit/197dacebad356b910d69fa69a719c2ad10cf49e6 (see "i18n-active_record":https://github.com/svenfuchs/i18n-active_record) +* "Improve exception handling":https://github.com/svenfuchs/i18n/commit/2913ff9a7544f223f60e7d7b32c2a0e1af89812b (deprectates I18n.default_exception_handler) +* "Change MissingTranslationData message to 'translation missing: foo.bar'":https://github.com/svenfuchs/i18n/commit/68fdfe47952325411afe5942e971ce10b2bdf900 +* "Expose MissingTranslationsData#keys method":https://github.com/svenfuchs/i18n/commit/3a37a389ecaac9670355b334e23e775549ee9822 +* "Improve Cascade#lookup (add default options)":https://github.com/svenfuchs/i18n/commit/0b9a1f2058a2be9543106cc19d08071c359511e1 +* "Finally remove deprecated interpolation syntax":https://github.com/svenfuchs/i18n/commit/2d43846d2b2a2e596f30fa58ea1c9ddb2243bb64 + +h2. 0.4.2 (2010-10-26) + +* "Improve UTF8 handling":http://github.com/svenfuchs/i18n/commit/e8d5820a3b08eeca28de1a2b9c8a6ad2b9e6476c +* "Expose I18n::VERSION":http://github.com/svenfuchs/i18n/commit/b832037bac94c7144f45f3ff5e3b4e4089781726 +* "Better deprecation output":http://github.com/svenfuchs/i18n/commit/2bee924464b8a9c33d3d7852eb1c8423aa38cc25 + +h2. 0.4.1 (2010-06-05) + +* "Fix interpolation failure on Ruby 1.9":http://github.com/svenfuchs/i18n/commit/8d45bedb11c4136c00e853d104b00a8e67ec4894 + +h2. 0.4.0 (2010-05-27) + +* "The localization proc also receives the object as option":http://github.com/svenfuchs/i18n/commit/4a8cd9fa660daaa3078e24c5851353ca377d9213 + +h2. 0.4.0.beta1 (2010-05-03) + +* "Renamed Fast backend to Memoize backend":http://github.com/svenfuchs/i18n/commit/f7f7dc12c00a19d3876223771e14f8671ff313cd + +* "Deprecate {{}} as interpolation syntax":http://github.com/svenfuchs/i18n/commit/8894ee521ef5788c415b625a6daf522af4c416e0 + +* "Allow nil translation to be stored again":http://github.com/svenfuchs/i18n/commit/f2074f1e82d10c2e9a801c8cc2f2a0c7c30703ba + +h2. 0.4.0.beta (2010-04-30) + +* "Added a KeyValue backend":http://github.com/svenfuchs/i18n/commit/28ca5f53ade7f545f8c0804e93564d4686b416a4 + +* "Added transliteration support":http://github.com/svenfuchs/i18n/commit/928fdb4794959e779e90f360eb01ba043672d8d5 + +* "Create Flatten backend module to aid handling flatten translations":http://github.com/svenfuchs/i18n/commit/2ec9d6998aa8facd7b15a3ef47a96cf2471cd8a1 + +* "Decouple the external separator (used when storing translations) from the internal separator in Fast and ActiveRecord backends":http://github.com/svenfuchs/i18n/commit/274cb4daa0ca5e3b2bd23b45eb7f9fc58f75a79d + +h2. 0.3.7 (2010-04-17) + +* "Speed up I18n.normalize_keys by caching reused normalizations and producing less garbage":http://github.com/svenfuchs/i18n/commit/819dac0fea9c29e6545801aa107e63e355728cd4 + +h2. 0.3.6 (2010-03-23) + +* "Move gettext po parser to lib":http://github.com/svenfuchs/i18n/commit/b2f038663b55727ac2327e6f07a46ba5d69d600c + +* "Move I18n configuration to I18n.config":http://github.com/svenfuchs/i18n/commit/4a7baea86663ead8c681008c3e80a622f0546b07 + +h2. 0.3.5 (2010-02-26) + +* "Delegate I18n.normalize_translation_keys to I18n.normalize_keys and deprecate +the former":http://github.com/svenfuchs/i18n/commit/7284b04d5f5dd9679cb68875515cdd0cdfc96fef + +h2. 0.3.4 (2010-02-25) + +* "Rename I18n.normalize_translation_keys to I18n.normalize_keys and finally make it public":http://github.com/svenfuchs/i18n/commit/20b05fe5802df6c90fb70a4e3760b2b851b791b3 + +* "Added CLDR supoprt":http://github.com/svenfuchs/i18n/commit/860eadf671a231e7f5dffb1bb27fa318ff7a8786 + +h2. 0.3.3 (2009-12-29) + +* "Use lib/i18n/version":http://github.com/svenfuchs/i18n/commit/ff426c8e7a2438b814cb303adadec292dacb752e + +* "Added a benchmark suite":http://github.com/svenfuchs/i18n/commit/f9b5b9b113097724638bdab96862ffa404e67e70 + +* "Ensure links can be handled recursively":http://github.com/svenfuchs/i18n/commit/2c50bd209f3fc24fe9dfa694c81be64340f09b7d + +* "Make sure we can lookup false values as translation data":http://github.com/svenfuchs/i18n/commit/561c82ba4b8921d03bfdf56cb2d0c2f287629001 + +* "Added Fast backend module":http://github.com/svenfuchs/i18n/commit/bd2f09f0a251ca793b0e8ecc7e32177a2f091c23 + +* "Added InterpolationCompiler backend module":http://github.com/svenfuchs/i18n/commit/91810887d1abfb28996a9183bc9004678290d28b + +h2. 0.3.2 (2009-12-12) + +* "Added Cascade backend":http://github.com/svenfuchs/i18n/commit/8009aef293e9ef8564c9005090d8380feabcaf6f + +h2. 0.3.1 (2009-12-11) + +* "Add PoParser to gemspec":http://github.com/svenfuchs/i18n/commit/d6b2763f39c932f66adb039b96882a472f883c51 +* "Enable custom separators for ActiveRecord backend":http://github.com/svenfuchs/i18n/commit/9341d3fcfc951cc31807ba672d2b5d90909ef3e5 +* "Pass interpolation values to interpolation procs":http://github.com/svenfuchs/i18n/commit/39c2ed8fbad645671cd5520ce7ad0aeefe2b0cca +* "Fix that ngettext supports keys with dots":http://github.com/svenfuchs/i18n/commit/7362a43c34364d500de8899cfcca6bf1a5e6d1c8 + +h2. 0.3.0 (2009-11-30) + +* "Gettext backend and helpers":http://github.com/svenfuchs/i18n/commit/35a1740d2f10b808548af352006950da4017e374 +* "Metadata module":http://github.com/svenfuchs/i18n/commit/2677208555179b36fcbe958c0e8bc642cf5bc020 +* "Basic ActiveRecord backend":http://github.com/svenfuchs/i18n/commit/786632d0b42de423ecf0969622efc87f1691e2a2 +* "Set encoding to UTF8 for all files":http://github.com/svenfuchs/i18n/commit/9be3d4a311b5bf583eec5d39986176cc40c112f2 +* "Chain backend":http://github.com/svenfuchs/i18n/commit/08259ffb88b3005403648d77bc1cbca0b92f3cf5 +* "Backend/cache implementation":http://github.com/svenfuchs/i18n/commit/e7bf15351cd2e27f5972eb40e65a5dd6f4a0feed +* "Pluralization module":http://github.com/svenfuchs/i18n/commit/9ca4c9ed52d4706566a6abeb2d78722dcc5d4764 +* "add and adapt Globalize2 fallback implementation":http://github.com/svenfuchs/i18n/commit/1b37a303b27d6222b17162804b06323e5628768f +* "move Simple backend implementation to a Base backend class and extend Simple from Base.":http://github.com/svenfuchs/i18n/commit/32ddc80a04e6aa247f6d6613bde7f78c73396cb4 + +h2. 0.2.0 (2009-07-12) + +* "Allow using Ruby 1.9 syntax for string interpolation (API addition)":http://github.com/svenfuchs/i18n/commit/c6e0b06d512f2af57199a843a1d8a40241b32861 +* "Allow configuring the default scope separator, allow to pass a custom scope separator(API addition)":http://github.com/svenfuchs/i18n/commit/5b75bfbc348061adc11e3790187a187275bfd471 (e.g. I18n.t(:'foo|bar', :separator => '|') +* "Pass :format option to #translate for #localize more useful lambda support":http://github.com/svenfuchs/i18n/commit/e277711b3c844fe7589b8d3f9af0f7d1b969a273 +* "Refactor Simple backend #resolve to #default and #resolve for more consistency. Now allows to pass lambdas as defaults and re-resolve Symbols":http://github.com/svenfuchs/i18n/commit/8c4ce3d923ce5fa73e973fe28217e18165549aba +* "Add lambda support to #translate (API addition)":http://github.com/svenfuchs/i18n/commit/c90e62d8f7d3d5b78f34cfe328d871b58884f115 +* "Add lambda support to #localize (API addition)":http://github.com/svenfuchs/i18n/commit/9d390afcf33f3f469bb95e6888147152f6cc7442 + +h2. 0.1.3 (2009-02-27) + +* "Remove unnecessary string encoding handling in the i18n simple backend which made the backend break on Ruby 1.9":http://github.com/svenfuchs/i18n/commit/4c3a970783861a94f2e89f46714fb3434e4f4f8d + +h2. 0.1.2 (2009-01-09) + +* "added #available_locales (returns an array of locales for which translations are available)":http://github.com/svenfuchs/i18n/commit/411f8fe7c8f3f89e9b6b921fa62ed66cb92f3af4 +* "flatten load_path before using it so that a nested array of paths won't throw up":http://github.com/svenfuchs/i18n/commit/d473a068a2b90aba98135deb225d6eb6d8104d70 + +h2. 0.1.1 (2008-11-20) + +* "Use :'en' as a default locale (in favor of :'en-US')":http://github.com/svenfuchs/i18n/commit/c4b10b246aecf7da78cb2568dd0d2ab7e6b8a230 +* "Add #reload! to Simple backend":http://github.com/svenfuchs/i18n/commit/36dd2bd9973b9e1559728749a9daafa44693e964 + +h2. 0.1.0 (2008-10-25) + +* "Fix Simple backend to distinguish false from nil values":http://github.com/svenfuchs/i18n/commit/39d9a47da14b5f3ba126af48923af8c30e135166 +* "Add #load_path to public api, add initialize to simple backend and remove #load_translations from public api":http://github.com/svenfuchs/i18n/commit/c4c5649e6bc8f020f1aaf5a5470bde048e22c82d +* "Speed up Backend::Simple#interpolate":http://github.com/svenfuchs/i18n/commit/9e1ac6bf8833304e036323ec9932b9f33c468a35 +* "Remove #populate and #store_translations from public API":http://github.com/svenfuchs/i18n/commit/f4e514a80be7feb509f66824ee311905e2940900 +* "Use :other instead of :many as a plural key":http://github.com/svenfuchs/i18n/commit/0f8f20a2552bf6a2aa758d8fdd62a7154e4a1bf6 +* "Use a class instead of a module for Simple backend":http://github.com/svenfuchs/i18n/commit/08f051aa61320c17debde24a83268bc74e33b995 +* "Make Simple backend #interpolate deal with non-ASCII string encodings":http://github.com/svenfuchs/i18n/commit/d84a3f3f55543c084d5dc5d1fed613b8df148789 +* "Fix default arrays of non-existant keys returning the default array":http://github.com/svenfuchs/i18n/commit/6c04ca86c87f97dc78f07c2a4023644e5ba8b839 + +h2. Initial implementation (June/July 2008) + +Initial implementation by "Sven Fuchs":http://www.workingwithrails.com/person/9963-sven-fuchs based on previous discussion/consensus of the rails-i18n team (alphabetical order) and many others: + +* "Matt Aimonetti":http://railsontherun.com +* "Sven Fuchs":http://www.workingwithrails.com/person/9963-sven-fuchs +* "Joshua Harvey":http://www.workingwithrails.com/person/759-joshua-harvey +* "Saimon Moore":http://saimonmoore.net +* "Stephan Soller":http://www.arkanis-development.de + +h2. More information + +* "Homepage":http://rails-i18n.org +* "Wiki":http://rails-i18n.org/wiki +* "Mailinglist":http://groups.google.com/group/rails-i18n +* "About the project/history":http://www.artweb-design.de/2008/7/18/finally-ruby-on-rails-gets-internationalized +* "Initial API Intro":http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-api diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/MIT-LICENSE b/vendor/ruby/1.9.1/gems/i18n-0.6.0/MIT-LICENSE new file mode 100755 index 0000000..ed8e9ee --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 The Ruby I18n team + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/README.textile b/vendor/ruby/1.9.1/gems/i18n-0.6.0/README.textile new file mode 100644 index 0000000..54e331f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/README.textile @@ -0,0 +1,103 @@ +h1. Ruby I18n + +Ruby Internationalization and localization solution. + +Features: + +* translation and localization +* interpolation of values to translations (Ruby 1.9 compatible syntax) +* pluralization (CLDR compatible) +* customizable transliteration to ASCII +* flexible defaults +* bulk lookup +* lambdas as translation data +* custom key/scope separator +* custom exception handlers +* extensible architecture with a swappable backend + +Pluggable features: + +* Cache +* Pluralization: lambda pluralizers stored as translation data +* Locale fallbacks, RFC4647 compliant (optionally: RFC4646 locale validation) +* Gettext support +* Translation metadata + +Alternative backends: + +* Chain +* ActiveRecord (optionally: ActiveRecord::Missing and ActiveRecord::StoreProcs) +* KeyValue (uses active_support/json and cannot store procs) + +For more information and lots of resources see: "http://ruby-i18n.org/wiki":http://ruby-i18n.org/wiki + +h2. Installation + +gem install i18n + +h4. Rails version warning + +On Rails < 2.3.6 the method I18n.localize will fail with MissingInterpolationArgument (issue "20":http://github.com/svenfuchs/i18n/issues/issue/20). Upgrade to Rails 2.3.6 or higher (2.3.8 preferably) is recommended. + +h3. Installation on Rails < 2.3.5 (deprecated) + +Up to version 2.3.4 Rails will not accept i18n gems > 0.1.3. There is an unpacked +gem inside of active_support/lib/vendor which gets loaded unless gem 'i18n', '~> 0.1.3'. +This requirement is relaxed in "6da03653":http://github.com/rails/rails/commit/6da03653 + +The new i18n gem can be loaded from vendor/plugins like this: + +
                        +  def reload_i18n!
                        +    raise "Move to i18n version 0.2.0 or greater" if Rails.version > "2.3.4"
                        +
                        +    $:.grep(/i18n/).each { |path| $:.delete(path) }
                        +    I18n::Backend.send :remove_const, "Simple"
                        +    $: << Rails.root.join('vendor', 'plugins', 'i18n', 'lib').to_s
                        +  end
                        +
                        + +Then you can `reload_i18n!` inside an i18n initializer. + +h2. Tests + +You can run tests both with + +* `rake test` or just `rake` +* run any test file directly, e.g. `ruby -Ilib -Itest test/api/simple_test.rb` +* run all tests with `ruby -Ilib -Itest test/all.rb` + +You can run all tests against all Gemfiles with + +* `ruby test/run_all.rb` + +The structure of the test suite is a bit unusual as it uses modules to reuse +particular tests in different test cases. + +The reason for this is that we need to enforce the I18n API across various +combinations of extensions. E.g. the Simple backend alone needs to support +the same API as any combination of feature and/or optimization modules included +to the Simple backend. We test this by reusing the same API defition (implemented +as test methods) in test cases with different setups. + +You can find the test cases that enforce the API in test/api. And you can find +the API definition test methods in test/api/tests. + +All other test cases (e.g. as defined in test/backend, test/core\_ext) etc. +follow the usual test setup and should be easy to grok. + +h2. Authors + +* "Sven Fuchs":http://www.artweb-design.de +* "Joshua Harvey":http://www.workingwithrails.com/person/759-joshua-harvey +* "Stephan Soller":http://www.arkanis-development.de +* "Saimon Moore":http://saimonmoore.net +* "Matt Aimonetti":http://railsontherun.com + +h2. Contributors + +http://github.com/svenfuchs/i18n/contributors + +h2. License + +MIT License. See the included MIT-LICENSE file. diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.no-rails b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.no-rails new file mode 100644 index 0000000..d4300c9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.no-rails @@ -0,0 +1,5 @@ +source :rubygems + +gem 'mocha' +gem 'test_declarative' + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.no-rails.lock b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.no-rails.lock new file mode 100644 index 0000000..569b32a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.no-rails.lock @@ -0,0 +1,14 @@ +GEM + remote: http://rubygems.org/ + specs: + mocha (0.9.9) + rake + rake (0.8.7) + test_declarative (0.0.4) + +PLATFORMS + ruby + +DEPENDENCIES + mocha + test_declarative diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-2.3.x b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-2.3.x new file mode 100644 index 0000000..8f8afbe --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-2.3.x @@ -0,0 +1,9 @@ +source :rubygems + +gem 'activesupport', '~> 2.3' +gem 'sqlite3-ruby' +gem 'mocha' +gem 'test_declarative' +gem 'rufus-tokyo' +gem 'ffi' + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-2.3.x.lock b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-2.3.x.lock new file mode 100644 index 0000000..6010615 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-2.3.x.lock @@ -0,0 +1,23 @@ +GEM + remote: http://rubygems.org/ + specs: + activesupport (2.3.10) + ffi (0.6.3) + rake (>= 0.8.7) + mocha (0.9.9) + rake + rake (0.8.7) + rufus-tokyo (1.0.7) + sqlite3-ruby (1.3.2) + test_declarative (0.0.4) + +PLATFORMS + ruby + +DEPENDENCIES + activesupport (~> 2.3) + ffi + mocha + rufus-tokyo + sqlite3-ruby + test_declarative diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-3.x b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-3.x new file mode 100644 index 0000000..782c844 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-3.x @@ -0,0 +1,9 @@ +source :rubygems + +gem 'activesupport', '~> 3.0.0' +gem 'sqlite3-ruby' +gem 'mocha' +gem 'test_declarative' +gem 'rufus-tokyo' +gem 'ffi' + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-3.x.lock b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-3.x.lock new file mode 100644 index 0000000..de7aad6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/ci/Gemfile.rails-3.x.lock @@ -0,0 +1,23 @@ +GEM + remote: http://rubygems.org/ + specs: + activesupport (3.0.3) + ffi (0.6.3) + rake (>= 0.8.7) + mocha (0.9.9) + rake + rake (0.8.7) + rufus-tokyo (1.0.7) + sqlite3-ruby (1.3.2) + test_declarative (0.0.4) + +PLATFORMS + ruby + +DEPENDENCIES + activesupport (~> 3.0.0) + ffi + mocha + rufus-tokyo + sqlite3-ruby + test_declarative diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n.rb new file mode 100755 index 0000000..b49479c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n.rb @@ -0,0 +1,331 @@ +require 'i18n/version' +require 'i18n/exceptions' +require 'i18n/interpolate/ruby' + +module I18n + autoload :Backend, 'i18n/backend' + autoload :Config, 'i18n/config' + autoload :Gettext, 'i18n/gettext' + autoload :Locale, 'i18n/locale' + autoload :Tests, 'i18n/tests' + + RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :throw, :raise, :rescue_format] + RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/ + + class << self + # Gets I18n configuration object. + def config + Thread.current[:i18n_config] ||= I18n::Config.new + end + + # Sets I18n configuration object. + def config=(value) + Thread.current[:i18n_config] = value + end + + # Write methods which delegates to the configuration object + %w(locale backend default_locale available_locales default_separator + exception_handler load_path).each do |method| + module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1 + def #{method} + config.#{method} + end + + def #{method}=(value) + config.#{method} = (value) + end + DELEGATORS + end + + # Tells the backend to reload translations. Used in situations like the + # Rails development environment. Backends can implement whatever strategy + # is useful. + def reload! + config.backend.reload! + end + + # Translates, pluralizes and interpolates a given key using a given locale, + # scope, and default, as well as interpolation values. + # + # *LOOKUP* + # + # Translation data is organized as a nested hash using the upper-level keys + # as namespaces. E.g., ActionView ships with the translation: + # :date => {:formats => {:short => "%b %d"}}. + # + # Translations can be looked up at any level of this hash using the key argument + # and the scope option. E.g., in this example I18n.t :date + # returns the whole translations hash {:formats => {:short => "%b %d"}}. + # + # Key can be either a single key or a dot-separated key (both Strings and Symbols + # work). E.g., the short format can be looked up using both: + # I18n.t 'date.formats.short' + # I18n.t :'date.formats.short' + # + # Scope can be either a single key, a dot-separated key or an array of keys + # or dot-separated keys. Keys and scopes can be combined freely. So these + # examples will all look up the same short date format: + # I18n.t 'date.formats.short' + # I18n.t 'formats.short', :scope => 'date' + # I18n.t 'short', :scope => 'date.formats' + # I18n.t 'short', :scope => %w(date formats) + # + # *INTERPOLATION* + # + # Translations can contain interpolation variables which will be replaced by + # values passed to #translate as part of the options hash, with the keys matching + # the interpolation variable names. + # + # E.g., with a translation :foo => "foo %{bar}" the option + # value for the key +bar+ will be interpolated into the translation: + # I18n.t :foo, :bar => 'baz' # => 'foo baz' + # + # *PLURALIZATION* + # + # Translation data can contain pluralized translations. Pluralized translations + # are arrays of singluar/plural versions of translations like ['Foo', 'Foos']. + # + # Note that I18n::Backend::Simple only supports an algorithm for English + # pluralization rules. Other algorithms can be supported by custom backends. + # + # This returns the singular version of a pluralized translation: + # I18n.t :foo, :count => 1 # => 'Foo' + # + # These both return the plural version of a pluralized translation: + # I18n.t :foo, :count => 0 # => 'Foos' + # I18n.t :foo, :count => 2 # => 'Foos' + # + # The :count option can be used both for pluralization and interpolation. + # E.g., with the translation + # :foo => ['%{count} foo', '%{count} foos'], count will + # be interpolated to the pluralized translation: + # I18n.t :foo, :count => 1 # => '1 foo' + # + # *DEFAULTS* + # + # This returns the translation for :foo or default if no translation was found: + # I18n.t :foo, :default => 'default' + # + # This returns the translation for :foo or the translation for :bar if no + # translation for :foo was found: + # I18n.t :foo, :default => :bar + # + # Returns the translation for :foo or the translation for :bar + # or default if no translations for :foo and :bar were found. + # I18n.t :foo, :default => [:bar, 'default'] + # + # *BULK LOOKUP* + # + # This returns an array with the translations for :foo and :bar. + # I18n.t [:foo, :bar] + # + # Can be used with dot-separated nested keys: + # I18n.t [:'baz.foo', :'baz.bar'] + # + # Which is the same as using a scope option: + # I18n.t [:foo, :bar], :scope => :baz + # + # *LAMBDAS* + # + # Both translations and defaults can be given as Ruby lambdas. Lambdas will be + # called and passed the key and options. + # + # E.g. assuming the key :salutation resolves to: + # lambda { |key, options| options[:gender] == 'm' ? "Mr. %{options[:name]}" : "Mrs. %{options[:name]}" } + # + # Then I18n.t(:salutation, :gender => 'w', :name => 'Smith') will result in "Mrs. Smith". + # + # It is recommended to use/implement lambdas in an "idempotent" way. E.g. when + # a cache layer is put in front of I18n.translate it will generate a cache key + # from the argument values passed to #translate. Therefor your lambdas should + # always return the same translations/values per unique combination of argument + # values. + def translate(*args) + options = args.last.is_a?(Hash) ? args.pop : {} + key = args.shift + backend = config.backend + locale = options.delete(:locale) || config.locale + handling = options.delete(:throw) && :throw || options.delete(:raise) && :raise # TODO deprecate :raise + + raise I18n::ArgumentError if key.is_a?(String) && key.empty? + + result = catch(:exception) do + if key.is_a?(Array) + key.map { |k| backend.translate(locale, k, options) } + else + backend.translate(locale, key, options) + end + end + result.is_a?(MissingTranslation) ? handle_exception(handling, result, locale, key, options) : result + end + alias :t :translate + + def translate!(key, options={}) + translate(key, options.merge(:raise => true)) + end + alias :t! :translate! + + # Transliterates UTF-8 characters to ASCII. By default this method will + # transliterate only Latin strings to an ASCII approximation: + # + # I18n.transliterate("Ærøskøbing") + # # => "AEroskobing" + # + # I18n.transliterate("日本語") + # # => "???" + # + # It's also possible to add support for per-locale transliterations. I18n + # expects transliteration rules to be stored at + # i18n.transliterate.rule. + # + # Transliteration rules can either be a Hash or a Proc. Procs must accept a + # single string argument. Hash rules inherit the default transliteration + # rules, while Procs do not. + # + # *Examples* + # + # Setting a Hash in .yml: + # + # i18n: + # transliterate: + # rule: + # ü: "ue" + # ö: "oe" + # + # Setting a Hash using Ruby: + # + # store_translations(:de, :i18n => { + # :transliterate => { + # :rule => { + # "ü" => "ue", + # "ö" => "oe" + # } + # } + # ) + # + # Setting a Proc: + # + # translit = lambda {|string| MyTransliterator.transliterate(string) } + # store_translations(:xx, :i18n => {:transliterate => {:rule => translit}) + # + # Transliterating strings: + # + # I18n.locale = :en + # I18n.transliterate("Jürgen") # => "Jurgen" + # I18n.locale = :de + # I18n.transliterate("Jürgen") # => "Juergen" + # I18n.transliterate("Jürgen", :locale => :en) # => "Jurgen" + # I18n.transliterate("Jürgen", :locale => :de) # => "Juergen" + def transliterate(*args) + options = args.pop if args.last.is_a?(Hash) + key = args.shift + locale = options && options.delete(:locale) || config.locale + raises = options && options.delete(:raise) + replacement = options && options.delete(:replacement) + config.backend.transliterate(locale, key, replacement) + rescue I18n::ArgumentError => exception + raise exception if raises + handle_exception(exception, locale, key, options) + end + + # Localizes certain objects, such as dates and numbers to local formatting. + def localize(object, options = {}) + locale = options.delete(:locale) || config.locale + format = options.delete(:format) || :default + config.backend.localize(locale, object, format, options) + end + alias :l :localize + + # Executes block with given I18n.locale set. + def with_locale(tmp_locale = nil) + if tmp_locale + current_locale = self.locale + self.locale = tmp_locale + end + yield + ensure + self.locale = current_locale if tmp_locale + end + + # Merges the given locale, key and scope into a single array of keys. + # Splits keys that contain dots into multiple keys. Makes sure all + # keys are Symbols. + def normalize_keys(locale, key, scope, separator = nil) + separator ||= I18n.default_separator + + keys = [] + keys.concat normalize_key(locale, separator) + keys.concat normalize_key(scope, separator) + keys.concat normalize_key(key, separator) + keys + end + + # making these private until Ruby 1.9.2 can send to protected methods again + # see http://redmine.ruby-lang.org/repositories/revision/ruby-19?rev=24280 + private + + # Any exceptions thrown in translate will be sent to the @@exception_handler + # which can be a Symbol, a Proc or any other Object unless they're forced to + # be raised or thrown (MissingTranslation). + # + # If exception_handler is a Symbol then it will simply be sent to I18n as + # a method call. A Proc will simply be called. In any other case the + # method #call will be called on the exception_handler object. + # + # Examples: + # + # I18n.exception_handler = :default_exception_handler # this is the default + # I18n.default_exception_handler(exception, locale, key, options) # will be called like this + # + # I18n.exception_handler = lambda { |*args| ... } # a lambda + # I18n.exception_handler.call(exception, locale, key, options) # will be called like this + # + # I18n.exception_handler = I18nExceptionHandler.new # an object + # I18n.exception_handler.call(exception, locale, key, options) # will be called like this + def handle_exception(handling, exception, locale, key, options) + case handling + when :raise + raise(exception.respond_to?(:to_exception) ? exception.to_exception : exception) + when :throw + throw :exception, exception + else + case handler = options[:exception_handler] || config.exception_handler + when Symbol + send(handler, exception, locale, key, options) + else + handler.call(exception, locale, key, options) + end + end + end + + def normalize_key(key, separator) + normalized_key_cache[separator][key] ||= + case key + when Array + key.map { |k| normalize_key(k, separator) }.flatten + else + keys = key.to_s.split(separator) + keys.delete('') + keys.map! { |k| k.to_sym } + keys + end + end + + def normalized_key_cache + @normalized_key_cache ||= Hash.new { |h,k| h[k] = {} } + end + + # DEPRECATED. Use I18n.normalize_keys instead. + def normalize_translation_keys(locale, key, scope, separator = nil) + puts "I18n.normalize_translation_keys is deprecated. Please use the class I18n.normalize_keys instead." + normalize_keys(locale, key, scope, separator) + end + + # DEPRECATED. Please use the I18n::ExceptionHandler class instead. + def default_exception_handler(exception, locale, key, options) + puts "I18n.default_exception_handler is deprecated. Please use the class I18n::ExceptionHandler instead " + + "(an instance of which is set to I18n.exception_handler by default)." + exception.is_a?(MissingTranslation) ? exception.message : raise(exception) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend.rb new file mode 100644 index 0000000..46ef054 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend.rb @@ -0,0 +1,18 @@ +module I18n + module Backend + autoload :Base, 'i18n/backend/base' + autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler' + autoload :Cache, 'i18n/backend/cache' + autoload :Cascade, 'i18n/backend/cascade' + autoload :Chain, 'i18n/backend/chain' + autoload :Fallbacks, 'i18n/backend/fallbacks' + autoload :Flatten, 'i18n/backend/flatten' + autoload :Gettext, 'i18n/backend/gettext' + autoload :KeyValue, 'i18n/backend/key_value' + autoload :Memoize, 'i18n/backend/memoize' + autoload :Metadata, 'i18n/backend/metadata' + autoload :Pluralization, 'i18n/backend/pluralization' + autoload :Simple, 'i18n/backend/simple' + autoload :Transliterator, 'i18n/backend/transliterator' + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/base.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/base.rb new file mode 100644 index 0000000..a9e70fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/base.rb @@ -0,0 +1,175 @@ +require 'yaml' +require 'i18n/core_ext/hash' +require 'i18n/core_ext/kernel/surpress_warnings' + +module I18n + module Backend + module Base + include I18n::Backend::Transliterator + + # Accepts a list of paths to translation files. Loads translations from + # plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml + # for details. + def load_translations(*filenames) + filenames = I18n.load_path if filenames.empty? + filenames.flatten.each { |filename| load_file(filename) } + end + + # This method receives a locale, a data hash and options for storing translations. + # Should be implemented + def store_translations(locale, data, options = {}) + raise NotImplementedError + end + + def translate(locale, key, options = {}) + raise InvalidLocale.new(locale) unless locale + entry = key && lookup(locale, key, options[:scope], options) + + if options.empty? + entry = resolve(locale, key, entry, options) + else + count, default = options.values_at(:count, :default) + values = options.except(*RESERVED_KEYS) + entry = entry.nil? && default ? + default(locale, key, default, options) : resolve(locale, key, entry, options) + end + + throw(:exception, I18n::MissingTranslation.new(locale, key, options)) if entry.nil? + entry = entry.dup if entry.is_a?(String) + + entry = pluralize(locale, entry, count) if count + entry = interpolate(locale, entry, values) if values + entry + end + + # Acts the same as +strftime+, but uses a localized version of the + # format string. Takes a key from the date/time formats translations as + # a format argument (e.g., :short in :'date.formats'). + def localize(locale, object, format = :default, options = {}) + raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime) + + if Symbol === format + key = format + type = object.respond_to?(:sec) ? 'time' : 'date' + options = options.merge(:raise => true, :object => object, :locale => locale) + format = I18n.t(:"#{type}.formats.#{key}", options) + end + + # format = resolve(locale, object, format, options) + format = format.to_s.gsub(/%[aAbBp]/) do |match| + case match + when '%a' then I18n.t(:"date.abbr_day_names", :locale => locale, :format => format)[object.wday] + when '%A' then I18n.t(:"date.day_names", :locale => locale, :format => format)[object.wday] + when '%b' then I18n.t(:"date.abbr_month_names", :locale => locale, :format => format)[object.mon] + when '%B' then I18n.t(:"date.month_names", :locale => locale, :format => format)[object.mon] + when '%p' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format) if object.respond_to? :hour + end + end + + object.strftime(format) + end + + # Returns an array of locales for which translations are available + # ignoring the reserved translation meta data key :i18n. + def available_locales + raise NotImplementedError + end + + def reload! + @skip_syntax_deprecation = false + end + + protected + + # The method which actually looks up for the translation in the store. + def lookup(locale, key, scope = [], options = {}) + raise NotImplementedError + end + + # Evaluates defaults. + # If given subject is an Array, it walks the array and returns the + # first translation that can be resolved. Otherwise it tries to resolve + # the translation directly. + def default(locale, object, subject, options = {}) + options = options.dup.reject { |key, value| key == :default } + case subject + when Array + subject.each do |item| + result = resolve(locale, object, item, options) and return result + end and nil + else + resolve(locale, object, subject, options) + end + end + + # Resolves a translation. + # If the given subject is a Symbol, it will be translated with the + # given options. If it is a Proc then it will be evaluated. All other + # subjects will be returned directly. + def resolve(locale, object, subject, options = {}) + return subject if options[:resolve] == false + result = catch(:exception) do + case subject + when Symbol + I18n.translate(subject, options.merge(:locale => locale, :throw => true)) + when Proc + date_or_time = options.delete(:object) || object + resolve(locale, object, subject.call(date_or_time, options)) + else + subject + end + end + result unless result.is_a?(MissingTranslation) + end + + # Picks a translation from an array according to English pluralization + # rules. It will pick the first translation if count is not equal to 1 + # and the second translation if it is equal to 1. Other backends can + # implement more flexible or complex pluralization rules. + def pluralize(locale, entry, count) + return entry unless entry.is_a?(Hash) && count + + key = :zero if count == 0 && entry.has_key?(:zero) + key ||= count == 1 ? :one : :other + raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key) + entry[key] + end + + # Interpolates values into a given string. + # + # interpolate "file %{file} opened by %%{user}", :file => 'test.txt', :user => 'Mr. X' + # # => "file test.txt opened by %{user}" + def interpolate(locale, string, values = {}) + if string.is_a?(::String) && !values.empty? + I18n.interpolate(string, values) + else + string + end + end + + # Loads a single translations file by delegating to #load_rb or + # #load_yml depending on the file extension and directly merges the + # data to the existing translations. Raises I18n::UnknownFileType + # for all other file extensions. + def load_file(filename) + type = File.extname(filename).tr('.', '').downcase + raise UnknownFileType.new(type, filename) unless respond_to?(:"load_#{type}", true) + data = send(:"load_#{type}", filename) + raise InvalidLocaleData.new(filename) unless data.is_a?(Hash) + data.each { |locale, d| store_translations(locale, d || {}) } + end + + # Loads a plain Ruby translations file. eval'ing the file must yield + # a Hash containing translation data with locales as toplevel keys. + def load_rb(filename) + eval(IO.read(filename), binding, filename) + end + + # Loads a YAML translations file. The data must have locales as + # toplevel keys. + def load_yml(filename) + YAML.load_file(filename) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/cache.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/cache.rb new file mode 100644 index 0000000..6757341 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/cache.rb @@ -0,0 +1,96 @@ +# This module allows you to easily cache all responses from the backend - thus +# speeding up the I18n aspects of your application quite a bit. +# +# To enable caching you can simply include the Cache module to the Simple +# backend - or whatever other backend you are using: +# +# I18n::Backend::Simple.include(I18n::Backend::Cache) +# +# You will also need to set a cache store implementation that you want to use: +# +# I18n.cache_store = ActiveSupport::Cache.lookup_store(:memory_store) +# +# You can use any cache implementation you want that provides the same API as +# ActiveSupport::Cache (only the methods #fetch and #write are being used). +# +# The cache_key implementation assumes that you only pass values to +# I18n.translate that return a valid key from #hash (see +# http://www.ruby-doc.org/core/classes/Object.html#M000337). +# +# If you use a lambda as a default value in your translation like this: +# +# I18n.t(:"date.order", :default => lambda {[:month, :day, :year]}) +# +# Then you will always have a cache miss, because each time this method +# is called the lambda will have a different hash value. If you know +# the result of the lambda is a constant as in the example above, then +# to cache this you can make the lambda a constant, like this: +# +# DEFAULT_DATE_ORDER = lambda {[:month, :day, :year]} +# ... +# I18n.t(:"date.order", :default => DEFAULT_DATE_ORDER) +# +# If the lambda may result in different values for each call then consider +# also using the Memoize backend. +# +module I18n + class << self + @@cache_store = nil + @@cache_namespace = nil + + def cache_store + @@cache_store + end + + def cache_store=(store) + @@cache_store = store + end + + def cache_namespace + @@cache_namespace + end + + def cache_namespace=(namespace) + @@cache_namespace = namespace + end + + def perform_caching? + !cache_store.nil? + end + end + + module Backend + # TODO Should the cache be cleared if new translations are stored? + module Cache + def translate(locale, key, options = {}) + I18n.perform_caching? ? fetch(cache_key(locale, key, options)) { super } : super + end + + protected + + def fetch(cache_key, &block) + result = _fetch(cache_key, &block) + throw(:exception, result) if result.is_a?(MissingTranslation) + result = result.dup if result.frozen? rescue result + result + end + + def _fetch(cache_key, &block) + result = I18n.cache_store.read(cache_key) and return result + result = catch(:exception, &block) + I18n.cache_store.write(cache_key, result) unless result.is_a?(Proc) + result + end + + def cache_key(locale, key, options) + # This assumes that only simple, native Ruby values are passed to I18n.translate. + "i18n/#{I18n.cache_namespace}/#{locale}/#{key.hash}/#{USE_INSPECT_HASH ? options.inspect.hash : options.hash}" + end + + private + # In Ruby < 1.9 the following is true: { :foo => 1, :bar => 2 }.hash == { :foo => 2, :bar => 1 }.hash + # Therefore we must use the hash of the inspect string instead to avoid cache key colisions. + USE_INSPECT_HASH = RUBY_VERSION <= "1.9" + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/cascade.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/cascade.rb new file mode 100644 index 0000000..66758a2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/cascade.rb @@ -0,0 +1,53 @@ +# The Cascade module adds the ability to do cascading lookups to backends that +# are compatible to the Simple backend. +# +# By cascading lookups we mean that for any key that can not be found the +# Cascade module strips one segment off the scope part of the key and then +# tries to look up the key in that scope. +# +# E.g. when a lookup for the key :"foo.bar.baz" does not yield a result then +# the segment :bar will be stripped off the scope part :"foo.bar" and the new +# scope :foo will be used to look up the key :baz. If that does not succeed +# then the remaining scope segment :foo will be omitted, too, and again the +# key :baz will be looked up (now with no scope). +# +# To enable a cascading lookup one passes the :cascade option: +# +# I18n.t(:'foo.bar.baz', :cascade => true) +# +# This will return the first translation found for :"foo.bar.baz", :"foo.baz" +# or :baz in this order. +# +# The cascading lookup takes precedence over resolving any given defaults. +# I.e. defaults will kick in after the cascading lookups haven't succeeded. +# +# This behavior is useful for libraries like ActiveRecord validations where +# the library wants to give users a bunch of more or less fine-grained options +# of scopes for a particular key. +# +# Thanks to Clemens Kofler for the initial idea and implementation! See +# http://github.com/clemens/i18n-cascading-backend + +module I18n + module Backend + module Cascade + def lookup(locale, key, scope = [], options = {}) + return super unless cascade = options[:cascade] + + cascade = { :step => 1 } unless cascade.is_a?(Hash) + step = cascade[:step] || 1 + offset = cascade[:offset] || 1 + separator = options[:separator] || I18n.default_separator + skip_root = cascade.has_key?(:skip_root) ? cascade[:skip_root] : true + + scope = I18n.normalize_keys(nil, key, scope, separator) + key = (scope.slice!(-offset, offset) || []).join(separator) + + begin + result = super + return result unless result.nil? + end while (!scope.empty? || !skip_root) && scope.slice!(-step, step) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/chain.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/chain.rb new file mode 100644 index 0000000..5a0c59b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/chain.rb @@ -0,0 +1,78 @@ +module I18n + module Backend + # Backend that chains multiple other backends and checks each of them when + # a translation needs to be looked up. This is useful when you want to use + # standard translations with a Simple backend but store custom application + # translations in a database or other backends. + # + # To use the Chain backend instantiate it and set it to the I18n module. + # You can add chained backends through the initializer or backends + # accessor: + # + # # preserves the existing Simple backend set to I18n.backend + # I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend) + # + # The implementation assumes that all backends added to the Chain implement + # a lookup method with the same API as Simple backend does. + class Chain + module Implementation + include Base + + attr_accessor :backends + + def initialize(*backends) + self.backends = backends + end + + def reload! + backends.each { |backend| backend.reload! } + end + + def store_translations(locale, data, options = {}) + backends.first.store_translations(locale, data, options) + end + + def available_locales + backends.map { |backend| backend.available_locales }.flatten.uniq + end + + def translate(locale, key, default_options = {}) + namespace = nil + options = default_options.except(:default) + + backends.each do |backend| + catch(:exception) do + options = default_options if backend == backends.last + translation = backend.translate(locale, key, options) + if namespace_lookup?(translation, options) + namespace ||= {} + namespace.merge!(translation) + elsif !translation.nil? + return translation + end + end + end + + return namespace if namespace + throw(:exception, I18n::MissingTranslation.new(locale, key, options)) + end + + def localize(locale, object, format = :default, options = {}) + backends.each do |backend| + catch(:exception) do + result = backend.localize(locale, object, format, options) and return result + end + end + throw(:exception, I18n::MissingTranslation.new(locale, format, options)) + end + + protected + def namespace_lookup?(result, options) + result.is_a?(Hash) && !options.has_key?(:count) + end + end + + include Implementation + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/fallbacks.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/fallbacks.rb new file mode 100644 index 0000000..70c2c04 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/fallbacks.rb @@ -0,0 +1,68 @@ +# I18n locale fallbacks are useful when you want your application to use +# translations from other locales when translations for the current locale are +# missing. E.g. you might want to use :en translations when translations in +# your applications main locale :de are missing. +# +# To enable locale fallbacks you can simply include the Fallbacks module to +# the Simple backend - or whatever other backend you are using: +# +# I18n::Backend::Simple.include(I18n::Backend::Fallbacks) +module I18n + @@fallbacks = nil + + class << self + # Returns the current fallbacks implementation. Defaults to +I18n::Locale::Fallbacks+. + def fallbacks + @@fallbacks ||= I18n::Locale::Fallbacks.new + end + + # Sets the current fallbacks implementation. Use this to set a different fallbacks implementation. + def fallbacks=(fallbacks) + @@fallbacks = fallbacks + end + end + + module Backend + module Fallbacks + # Overwrites the Base backend translate method so that it will try each + # locale given by I18n.fallbacks for the given locale. E.g. for the + # locale :"de-DE" it might try the locales :"de-DE", :de and :en + # (depends on the fallbacks implementation) until it finds a result with + # the given options. If it does not find any result for any of the + # locales it will then throw MissingTranslation as usual. + # + # The default option takes precedence over fallback locales + # only when it's a Symbol. When the default contains a String or a Proc + # it is evaluated last after all the fallback locales have been tried. + def translate(locale, key, options = {}) + return super if options[:fallback] + default = extract_string_or_lambda_default!(options) if options[:default] + + options[:fallback] = true + I18n.fallbacks[locale].each do |fallback| + catch(:exception) do + result = super(fallback, key, options) + return result unless result.nil? + end + end + options.delete(:fallback) + + return super(locale, nil, options.merge(:default => default)) if default + throw(:exception, I18n::MissingTranslation.new(locale, key, options)) + end + + def extract_string_or_lambda_default!(options) + defaults = [options[:default]].flatten + if index = find_first_string_or_lambda_default(defaults) + options[:default] = defaults[0, index] + defaults[index] + end + end + + def find_first_string_or_lambda_default(defaults) + defaults.each_with_index { |default, ix| return ix if String === default || Proc === default } + nil + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/flatten.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/flatten.rb new file mode 100644 index 0000000..c23f7c1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/flatten.rb @@ -0,0 +1,113 @@ +module I18n + module Backend + # This module contains several helpers to assist flattening translations. + # You may want to flatten translations for: + # + # 1) speed up lookups, as in the Memoize backend; + # 2) In case you want to store translations in a data store, as in ActiveRecord backend; + # + # You can check both backends above for some examples. + # This module also keeps all links in a hash so they can be properly resolved when flattened. + module Flatten + SEPARATOR_ESCAPE_CHAR = "\001" + FLATTEN_SEPARATOR = "." + + # normalize_keys the flatten way. This method is significantly faster + # and creates way less objects than the one at I18n.normalize_keys. + # It also handles escaping the translation keys. + def self.normalize_flat_keys(locale, key, scope, separator) + keys = [scope, key].flatten.compact + separator ||= I18n.default_separator + + if separator != FLATTEN_SEPARATOR + keys.map! do |k| + k.to_s.tr("#{FLATTEN_SEPARATOR}#{separator}", + "#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}") + end + end + + keys.join(".") + end + + # Receives a string and escape the default separator. + def self.escape_default_separator(key) #:nodoc: + key.to_s.tr(FLATTEN_SEPARATOR, SEPARATOR_ESCAPE_CHAR) + end + + # Shortcut to I18n::Backend::Flatten.normalize_flat_keys + # and then resolve_links. + def normalize_flat_keys(locale, key, scope, separator) + key = I18n::Backend::Flatten.normalize_flat_keys(locale, key, scope, separator) + resolve_link(locale, key) + end + + # Store flattened links. + def links + @links ||= Hash.new { |h,k| h[k] = {} } + end + + # Flatten keys for nested Hashes by chaining up keys: + # + # >> { "a" => { "b" => { "c" => "d", "e" => "f" }, "g" => "h" }, "i" => "j"}.wind + # => { "a.b.c" => "d", "a.b.e" => "f", "a.g" => "h", "i" => "j" } + # + def flatten_keys(hash, escape, prev_key=nil, &block) + hash.each_pair do |key, value| + key = escape_default_separator(key) if escape + curr_key = [prev_key, key].compact.join(FLATTEN_SEPARATOR).to_sym + yield curr_key, value + flatten_keys(value, escape, curr_key, &block) if value.is_a?(Hash) + end + end + + # Receives a hash of translations (where the key is a locale and + # the value is another hash) and return a hash with all + # translations flattened. + # + # Nested hashes are included in the flattened hash just if subtree + # is true and Symbols are automatically stored as links. + def flatten_translations(locale, data, escape, subtree) + hash = {} + flatten_keys(data, escape) do |key, value| + if value.is_a?(Hash) + hash[key] = value if subtree + else + store_link(locale, key, value) if value.is_a?(Symbol) + hash[key] = value + end + end + hash + end + + protected + + def store_link(locale, key, link) + links[locale.to_sym][key.to_s] = link.to_s + end + + def resolve_link(locale, key) + key, locale = key.to_s, locale.to_sym + links = self.links[locale] + + if links.key?(key) + links[key] + elsif link = find_link(locale, key) + store_link(locale, key, key.gsub(*link)) + else + key + end + end + + def find_link(locale, key) #:nodoc: + links[locale].each do |from, to| + return [from, to] if key[0, from.length] == from + end && nil + end + + def escape_default_separator(key) #:nodoc: + I18n::Backend::Flatten.escape_default_separator(key) + end + + end + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/gettext.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/gettext.rb new file mode 100644 index 0000000..f84ff2d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/gettext.rb @@ -0,0 +1,71 @@ +require 'i18n/gettext' +require 'i18n/gettext/po_parser' + +# Experimental support for using Gettext po files to store translations. +# +# To use this you can simply include the module to the Simple backend - or +# whatever other backend you are using. +# +# I18n::Backend::Simple.include(I18n::Backend::Gettext) +# +# Now you should be able to include your Gettext translation (*.po) files to +# the I18n.load_path so they're loaded to the backend and you can use them as +# usual: +# +# I18n.load_path += Dir["path/to/locales/*.po"] +# +# Following the Gettext convention this implementation expects that your +# translation files are named by their locales. E.g. the file en.po would +# contain the translations for the English locale. +module I18n + module Backend + module Gettext + class PoData < Hash + def set_comment(msgid_or_sym, comment) + # ignore + end + end + + protected + def load_po(filename) + locale = ::File.basename(filename, '.po').to_sym + data = normalize(locale, parse(filename)) + { locale => data } + end + + def parse(filename) + GetText::PoParser.new.parse(::File.read(filename), PoData.new) + end + + def normalize(locale, data) + data.inject({}) do |result, (key, value)| + unless key.nil? || key.empty? + key, value = normalize_pluralization(locale, key, value) if key.index("\000") + + parts = key.split('|').reverse + normalized = parts.inject({}) do |_normalized, part| + { part => _normalized.empty? ? value : _normalized } + end + + result.deep_merge!(normalized) + end + result + end + end + + def normalize_pluralization(locale, key, value) + # FIXME po_parser includes \000 chars that can not be turned into Symbols + key = key.gsub("\000", I18n::Gettext::PLURAL_SEPARATOR).split(I18n::Gettext::PLURAL_SEPARATOR).first + + keys = I18n::Gettext.plural_keys(locale) + values = value.split("\000") + raise "invalid number of plurals: #{values.size}, keys: #{keys.inspect}" if values.size != keys.size + + result = {} + values.each_with_index { |_value, ix| result[keys[ix]] = _value } + [key, result] + end + + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/interpolation_compiler.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/interpolation_compiler.rb new file mode 100644 index 0000000..fc8a3a1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/interpolation_compiler.rb @@ -0,0 +1,121 @@ +# The InterpolationCompiler module contains optimizations that can tremendously +# speed up the interpolation process on the Simple backend. +# +# It works by defining a pre-compiled method on stored translation Strings that +# already bring all the knowledge about contained interpolation variables etc. +# so that the actual recurring interpolation will be very fast. +# +# To enable pre-compiled interpolations you can simply include the +# InterpolationCompiler module to the Simple backend: +# +# I18n::Backend::Simple.include(I18n::Backend::InterpolationCompiler) +# +# Note that InterpolationCompiler does not yield meaningful results and consequently +# should not be used with Ruby 1.9 (YARV) but improves performance everywhere else +# (jRuby, Rubinius and 1.8.7). +module I18n + module Backend + module InterpolationCompiler + module Compiler + extend self + + TOKENIZER = /(%%\{[^\}]+\}|%\{[^\}]+\})/ + INTERPOLATION_SYNTAX_PATTERN = /(%)?(%\{([^\}]+)\})/ + + def compile_if_an_interpolation(string) + if interpolated_str?(string) + string.instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + def i18n_interpolate(v = {}) + "#{compiled_interpolation_body(string)}" + end + RUBY_EVAL + end + + string + end + + def interpolated_str?(str) + str.kind_of?(::String) && str =~ INTERPOLATION_SYNTAX_PATTERN + end + + protected + # tokenize("foo %{bar} baz %%{buz}") # => ["foo ", "%{bar}", " baz ", "%%{buz}"] + def tokenize(str) + str.split(TOKENIZER) + end + + def compiled_interpolation_body(str) + tokenize(str).map do |token| + (matchdata = token.match(INTERPOLATION_SYNTAX_PATTERN)) ? handle_interpolation_token(token, matchdata) : escape_plain_str(token) + end.join + end + + def handle_interpolation_token(interpolation, matchdata) + escaped, pattern, key = matchdata.values_at(1, 2, 3) + escaped ? pattern : compile_interpolation_token(key.to_sym) + end + + def compile_interpolation_token(key) + "\#{#{interpolate_or_raise_missing(key)}}" + end + + def interpolate_or_raise_missing(key) + escaped_key = escape_key_sym(key) + RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key) + end + + def interpolate_key(key) + [direct_key(key), nil_key(key), missing_key(key)].join('||') + end + + def direct_key(key) + "((t = v[#{key}]) && t.respond_to?(:call) ? t.call : t)" + end + + def nil_key(key) + "(v.has_key?(#{key}) && '')" + end + + def missing_key(key) + "raise(MissingInterpolationArgument.new(#{key}, self))" + end + + def reserved_key(key) + "raise(ReservedInterpolationKey.new(#{key}, self))" + end + + def escape_plain_str(str) + str.gsub(/"|\\|#/) {|x| "\\#{x}"} + end + + def escape_key_sym(key) + # rely on Ruby to do all the hard work :) + key.to_sym.inspect + end + end + + def interpolate(locale, string, values) + if string.respond_to?(:i18n_interpolate) + string.i18n_interpolate(values) + elsif values + super + else + string + end + end + + def store_translations(locale, data, options = {}) + compile_all_strings_in(data) + super + end + + protected + def compile_all_strings_in(data) + data.each_value do |value| + Compiler.compile_if_an_interpolation(value) + compile_all_strings_in(value) if value.kind_of?(Hash) + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/key_value.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/key_value.rb new file mode 100644 index 0000000..df80718 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/key_value.rb @@ -0,0 +1,101 @@ +require 'i18n/backend/base' +require 'active_support/json' +require 'active_support/ordered_hash' # active_support/json/encoding uses ActiveSupport::OrderedHash but does not require it + +module I18n + module Backend + # This is a basic backend for key value stores. It receives on + # initialization the store, which should respond to three methods: + # + # * store#[](key) - Used to get a value + # * store#[]=(key, value) - Used to set a value + # * store#keys - Used to get all keys + # + # Since these stores only supports string, all values are converted + # to JSON before being stored, allowing it to also store booleans, + # hashes and arrays. However, this store does not support Procs. + # + # As the ActiveRecord backend, Symbols are just supported when loading + # translations from the filesystem or through explicit store translations. + # + # Also, avoid calling I18n.available_locales since it's a somehow + # expensive operation in most stores. + # + # == Example + # + # To setup I18n to use TokyoCabinet in memory is quite straightforward: + # + # require 'rufus/tokyo/cabinet' # gem install rufus-tokyo + # I18n.backend = I18n::Backend::KeyValue.new(Rufus::Tokyo::Cabinet.new('*')) + # + # == Performance + # + # You may make this backend even faster by including the Memoize module. + # However, notice that you should properly clear the cache if you change + # values directly in the key-store. + # + # == Subtrees + # + # In most backends, you are allowed to retrieve part of a translation tree: + # + # I18n.backend.store_translations :en, :foo => { :bar => :baz } + # I18n.t "foo" #=> { :bar => :baz } + # + # This backend supports this feature by default, but it slows down the storage + # of new data considerably and makes hard to delete entries. That said, you are + # allowed to disable the storage of subtrees on initialization: + # + # I18n::Backend::KeyValue.new(@store, false) + # + # This is useful if you are using a KeyValue backend chained to a Simple backend. + class KeyValue + module Implementation + attr_accessor :store + + include Base, Flatten + + def initialize(store, subtrees=true) + @store, @subtrees = store, subtrees + end + + def store_translations(locale, data, options = {}) + escape = options.fetch(:escape, true) + flatten_translations(locale, data, escape, @subtrees).each do |key, value| + key = "#{locale}.#{key}" + + case value + when Hash + if @subtrees && (old_value = @store[key]) + old_value = ActiveSupport::JSON.decode(old_value) + value = old_value.deep_symbolize_keys.deep_merge!(value) if old_value.is_a?(Hash) + end + when Proc + raise "Key-value stores cannot handle procs" + end + + @store[key] = ActiveSupport::JSON.encode(value) unless value.is_a?(Symbol) + end + end + + def available_locales + locales = @store.keys.map { |k| k =~ /\./; $` } + locales.uniq! + locales.compact! + locales.map! { |k| k.to_sym } + locales + end + + protected + + def lookup(locale, key, scope = [], options = {}) + key = normalize_flat_keys(locale, key, scope, options[:separator]) + value = @store["#{locale}.#{key}"] + value = ActiveSupport::JSON.decode(value) if value + value.is_a?(Hash) ? value.deep_symbolize_keys : value + end + end + + include Implementation + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/memoize.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/memoize.rb new file mode 100644 index 0000000..ae9801f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/memoize.rb @@ -0,0 +1,46 @@ +# Memoize module simply memoizes the values returned by lookup using +# a flat hash and can tremendously speed up the lookup process in a backend. +# +# To enable it you can simply include the Memoize module to your backend: +# +# I18n::Backend::Simple.include(I18n::Backend::Memoize) +# +# Notice that it's the responsibility of the backend to define whenever the +# cache should be cleaned. +module I18n + module Backend + module Memoize + def available_locales + @memoized_locales ||= super + end + + def store_translations(locale, data, options = {}) + reset_memoizations!(locale) + super + end + + def reload! + reset_memoizations! + super + end + + protected + + def lookup(locale, key, scope = nil, options = {}) + flat_key = I18n::Backend::Flatten.normalize_flat_keys(locale, + key, scope, options[:separator]).to_sym + flat_hash = memoized_lookup[locale.to_sym] + flat_hash.key?(flat_key) ? flat_hash[flat_key] : (flat_hash[flat_key] = super) + end + + def memoized_lookup + @memoized_lookup ||= Hash.new { |h, k| h[k] = {} } + end + + def reset_memoizations!(locale=nil) + @memoized_locales = nil + (locale ? memoized_lookup[locale.to_sym] : memoized_lookup).clear + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/metadata.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/metadata.rb new file mode 100644 index 0000000..52c0a29 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/metadata.rb @@ -0,0 +1,65 @@ +# I18n translation metadata is useful when you want to access information +# about how a translation was looked up, pluralized or interpolated in +# your application. +# +# msg = I18n.t(:message, :default => 'Hi!', :scope => :foo) +# msg.translation_metadata +# # => { :key => :message, :scope => :foo, :default => 'Hi!' } +# +# If a :count option was passed to #translate it will be set to the metadata. +# Likewise, if any interpolation variables were passed they will also be set. +# +# To enable translation metadata you can simply include the Metadata module +# into the Simple backend class - or whatever other backend you are using: +# +# I18n::Backend::Simple.include(I18n::Backend::Metadata) +# +module I18n + module Backend + module Metadata + class << self + def included(base) + Object.class_eval do + def translation_metadata + @translation_metadata ||= {} + end + + def translation_metadata=(translation_metadata) + @translation_metadata = translation_metadata + end + end unless Object.method_defined?(:translation_metadata) + end + end + + def translate(locale, key, options = {}) + metadata = { + :locale => locale, + :key => key, + :scope => options[:scope], + :default => options[:default], + :separator => options[:separator], + :values => options.reject { |name, value| RESERVED_KEYS.include?(name) } + } + with_metadata(metadata) { super } + end + + def interpolate(locale, entry, values = {}) + metadata = entry.translation_metadata.merge(:original => entry) + with_metadata(metadata) { super } + end + + def pluralize(locale, entry, count) + with_metadata(:count => count) { super } + end + + protected + + def with_metadata(metadata, &block) + result = yield + result.translation_metadata = result.translation_metadata.merge(metadata) if result + result + end + + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/pluralization.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/pluralization.rb new file mode 100644 index 0000000..875040c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/pluralization.rb @@ -0,0 +1,55 @@ +# I18n locale fallbacks are useful when you want your application to use +# translations from other locales when translations for the current locale are +# missing. E.g. you might want to use :en translations when translations in +# your applications main locale :de are missing. +# +# To enable locale specific pluralizations you can simply include the +# Pluralization module to the Simple backend - or whatever other backend you +# are using. +# +# I18n::Backend::Simple.include(I18n::Backend::Pluralization) +# +# You also need to make sure to provide pluralization algorithms to the +# backend, i.e. include them to your I18n.load_path accordingly. +module I18n + module Backend + module Pluralization + # Overwrites the Base backend translate method so that it will check the + # translation meta data space (:i18n) for a locale specific pluralization + # rule and use it to pluralize the given entry. I.e. the library expects + # pluralization rules to be stored at I18n.t(:'i18n.plural.rule') + # + # Pluralization rules are expected to respond to #call(count) and + # return a pluralization key. Valid keys depend on the translation data + # hash (entry) but it is generally recommended to follow CLDR's style, + # i.e., return one of the keys :zero, :one, :few, :many, :other. + # + # The :zero key is always picked directly when count equals 0 AND the + # translation data has the key :zero. This way translators are free to + # either pick a special :zero translation even for languages where the + # pluralizer does not return a :zero key. + def pluralize(locale, entry, count) + return entry unless entry.is_a?(Hash) and count + + pluralizer = pluralizer(locale) + if pluralizer.respond_to?(:call) + key = count == 0 && entry.has_key?(:zero) ? :zero : pluralizer.call(count) + raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key) + entry[key] + else + super + end + end + + protected + + def pluralizers + @pluralizers ||= {} + end + + def pluralizer(locale) + pluralizers[locale] ||= I18n.t(:'i18n.plural.rule', :locale => locale, :resolve => false) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/simple.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/simple.rb new file mode 100644 index 0000000..95ffb6a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/simple.rb @@ -0,0 +1,87 @@ +module I18n + module Backend + # A simple backend that reads translations from YAML files and stores them in + # an in-memory hash. Relies on the Base backend. + # + # The implementation is provided by a Implementation module allowing to easily + # extend Simple backend's behavior by including modules. E.g.: + # + # module I18n::Backend::Pluralization + # def pluralize(*args) + # # extended pluralization logic + # super + # end + # end + # + # I18n::Backend::Simple.include(I18n::Backend::Pluralization) + class Simple + (class << self; self; end).class_eval { public :include } + + module Implementation + include Base + + def initialized? + @initialized ||= false + end + + # Stores translations for the given locale in memory. + # This uses a deep merge for the translations hash, so existing + # translations will be overwritten by new ones only at the deepest + # level of the hash. + def store_translations(locale, data, options = {}) + locale = locale.to_sym + translations[locale] ||= {} + data = data.deep_symbolize_keys + translations[locale].deep_merge!(data) + end + + # Get available locales from the translations hash + def available_locales + init_translations unless initialized? + translations.inject([]) do |locales, (locale, data)| + locales << locale unless (data.keys - [:i18n]).empty? + locales + end + end + + # Clean up translations hash and set initialized to false on reload! + def reload! + @initialized = false + @translations = nil + super + end + + protected + + def init_translations + load_translations + @initialized = true + end + + def translations + @translations ||= {} + end + + # Looks up a translation from the translations hash. Returns nil if + # eiher key is nil, or locale, scope or key do not exist as a key in the + # nested translations hash. Splits keys or scopes containing dots + # into multiple keys, i.e. currency.format is regarded the same as + # %w(currency format). + def lookup(locale, key, scope = [], options = {}) + init_translations unless initialized? + keys = I18n.normalize_keys(locale, key, scope, options[:separator]) + + keys.inject(translations) do |result, _key| + _key = _key.to_sym + return nil unless result.is_a?(Hash) && result.has_key?(_key) + result = result[_key] + result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol) + result + end + end + end + + include Implementation + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/transliterator.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/transliterator.rb new file mode 100644 index 0000000..2ce2cc8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/backend/transliterator.rb @@ -0,0 +1,98 @@ +# encoding: utf-8 +module I18n + module Backend + module Transliterator + DEFAULT_REPLACEMENT_CHAR = "?" + + # Given a locale and a UTF-8 string, return the locale's ASCII + # approximation for the string. + def transliterate(locale, string, replacement = nil) + @transliterators ||= {} + @transliterators[locale] ||= Transliterator.get I18n.t(:'i18n.transliterate.rule', + :locale => locale, :resolve => false, :default => {}) + @transliterators[locale].transliterate(string, replacement) + end + + # Get a transliterator instance. + def self.get(rule = nil) + if !rule || rule.kind_of?(Hash) + HashTransliterator.new(rule) + elsif rule.kind_of? Proc + ProcTransliterator.new(rule) + else + raise I18n::ArgumentError, "Transliteration rule must be a proc or a hash." + end + end + + # A transliterator which accepts a Proc as its transliteration rule. + class ProcTransliterator + def initialize(rule) + @rule = rule + end + + def transliterate(string, replacement = nil) + @rule.call(string) + end + end + + # A transliterator which accepts a Hash of characters as its translation + # rule. + class HashTransliterator + DEFAULT_APPROXIMATIONS = { + "À"=>"A", "Ã"=>"A", "Â"=>"A", "Ã"=>"A", "Ä"=>"A", "Ã…"=>"A", "Æ"=>"AE", + "Ç"=>"C", "È"=>"E", "É"=>"E", "Ê"=>"E", "Ë"=>"E", "ÃŒ"=>"I", "Ã"=>"I", + "ÃŽ"=>"I", "Ã"=>"I", "Ã"=>"D", "Ñ"=>"N", "Ã’"=>"O", "Ó"=>"O", "Ô"=>"O", + "Õ"=>"O", "Ö"=>"O", "×"=>"x", "Ø"=>"O", "Ù"=>"U", "Ú"=>"U", "Û"=>"U", + "Ãœ"=>"U", "Ã"=>"Y", "Þ"=>"Th", "ß"=>"ss", "à"=>"a", "á"=>"a", "â"=>"a", + "ã"=>"a", "ä"=>"a", "Ã¥"=>"a", "æ"=>"ae", "ç"=>"c", "è"=>"e", "é"=>"e", + "ê"=>"e", "ë"=>"e", "ì"=>"i", "í"=>"i", "î"=>"i", "ï"=>"i", "ð"=>"d", + "ñ"=>"n", "ò"=>"o", "ó"=>"o", "ô"=>"o", "õ"=>"o", "ö"=>"o", "ø"=>"o", + "ù"=>"u", "ú"=>"u", "û"=>"u", "ü"=>"u", "ý"=>"y", "þ"=>"th", "ÿ"=>"y", + "Ä€"=>"A", "Ä"=>"a", "Ä‚"=>"A", "ă"=>"a", "Ä„"=>"A", "Ä…"=>"a", "Ć"=>"C", + "ć"=>"c", "Ĉ"=>"C", "ĉ"=>"c", "ÄŠ"=>"C", "Ä‹"=>"c", "ÄŒ"=>"C", "Ä"=>"c", + "ÄŽ"=>"D", "Ä"=>"d", "Ä"=>"D", "Ä‘"=>"d", "Ä’"=>"E", "Ä“"=>"e", "Ä”"=>"E", + "Ä•"=>"e", "Ä–"=>"E", "Ä—"=>"e", "Ę"=>"E", "Ä™"=>"e", "Äš"=>"E", "Ä›"=>"e", + "Äœ"=>"G", "Ä"=>"g", "Äž"=>"G", "ÄŸ"=>"g", "Ä "=>"G", "Ä¡"=>"g", "Ä¢"=>"G", + "Ä£"=>"g", "Ĥ"=>"H", "Ä¥"=>"h", "Ħ"=>"H", "ħ"=>"h", "Ĩ"=>"I", "Ä©"=>"i", + "Ī"=>"I", "Ä«"=>"i", "Ĭ"=>"I", "Ä­"=>"i", "Ä®"=>"I", "į"=>"i", "Ä°"=>"I", + "ı"=>"i", "IJ"=>"IJ", "ij"=>"ij", "Ä´"=>"J", "ĵ"=>"j", "Ķ"=>"K", "Ä·"=>"k", + "ĸ"=>"k", "Ĺ"=>"L", "ĺ"=>"l", "Ä»"=>"L", "ļ"=>"l", "Ľ"=>"L", "ľ"=>"l", + "Ä¿"=>"L", "Å€"=>"l", "Å"=>"L", "Å‚"=>"l", "Ń"=>"N", "Å„"=>"n", "Å…"=>"N", + "ņ"=>"n", "Ň"=>"N", "ň"=>"n", "ʼn"=>"'n", "ÅŠ"=>"NG", "Å‹"=>"ng", + "ÅŒ"=>"O", "Å"=>"o", "ÅŽ"=>"O", "Å"=>"o", "Å"=>"O", "Å‘"=>"o", "Å’"=>"OE", + "Å“"=>"oe", "Å”"=>"R", "Å•"=>"r", "Å–"=>"R", "Å—"=>"r", "Ř"=>"R", "Å™"=>"r", + "Åš"=>"S", "Å›"=>"s", "Åœ"=>"S", "Å"=>"s", "Åž"=>"S", "ÅŸ"=>"s", "Å "=>"S", + "Å¡"=>"s", "Å¢"=>"T", "Å£"=>"t", "Ť"=>"T", "Å¥"=>"t", "Ŧ"=>"T", "ŧ"=>"t", + "Ũ"=>"U", "Å©"=>"u", "Ū"=>"U", "Å«"=>"u", "Ŭ"=>"U", "Å­"=>"u", "Å®"=>"U", + "ů"=>"u", "Å°"=>"U", "ű"=>"u", "Ų"=>"U", "ų"=>"u", "Å´"=>"W", "ŵ"=>"w", + "Ŷ"=>"Y", "Å·"=>"y", "Ÿ"=>"Y", "Ź"=>"Z", "ź"=>"z", "Å»"=>"Z", "ż"=>"z", + "Ž"=>"Z", "ž"=>"z" + } + + def initialize(rule = nil) + @rule = rule + add DEFAULT_APPROXIMATIONS + add rule if rule + end + + def transliterate(string, replacement = nil) + string.gsub(/[^\x00-\x7f]/u) do |char| + approximations[char] || replacement || DEFAULT_REPLACEMENT_CHAR + end + end + + private + + def approximations + @approximations ||= {} + end + + # Add transliteration rules to the approximations hash. + def add(hash) + hash.keys.each {|key| hash[key.to_s] = hash.delete(key).to_s} + approximations.merge! hash + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/config.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/config.rb new file mode 100644 index 0000000..5fe05f7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/config.rb @@ -0,0 +1,86 @@ +module I18n + class Config + # The only configuration value that is not global and scoped to thread is :locale. + # It defaults to the default_locale. + def locale + @locale ||= default_locale + end + + # Sets the current locale pseudo-globally, i.e. in the Thread.current hash. + def locale=(locale) + @locale = locale.to_sym rescue nil + end + + # Returns the current backend. Defaults to +Backend::Simple+. + def backend + @@backend ||= Backend::Simple.new + end + + # Sets the current backend. Used to set a custom backend. + def backend=(backend) + @@backend = backend + end + + # Returns the current default locale. Defaults to :'en' + def default_locale + @@default_locale ||= :en + end + + # Sets the current default locale. Used to set a custom default locale. + def default_locale=(locale) + @@default_locale = locale.to_sym rescue nil + end + + # Returns an array of locales for which translations are available. + # Unless you explicitely set these through I18n.available_locales= + # the call will be delegated to the backend. + def available_locales + @@available_locales ||= nil + @@available_locales || backend.available_locales + end + + # Sets the available locales. + def available_locales=(locales) + @@available_locales = Array(locales).map { |locale| locale.to_sym } + @@available_locales = nil if @@available_locales.empty? + end + + # Returns the current default scope separator. Defaults to '.' + def default_separator + @@default_separator ||= '.' + end + + # Sets the current default scope separator. + def default_separator=(separator) + @@default_separator = separator + end + + # Return the current exception handler. Defaults to :default_exception_handler. + def exception_handler + @@exception_handler ||= ExceptionHandler.new + end + + # Sets the exception handler. + def exception_handler=(exception_handler) + @@exception_handler = exception_handler + end + + # Allow clients to register paths providing translation data sources. The + # backend defines acceptable sources. + # + # E.g. the provided SimpleBackend accepts a list of paths to translation + # files which are either named *.rb and contain plain Ruby Hashes or are + # named *.yml and contain YAML data. So for the SimpleBackend clients may + # register translation files like this: + # I18n.load_path << 'path/to/locale/en.yml' + def load_path + @@load_path ||= [] + end + + # Sets the load path instance. Custom implementations are expected to + # behave like a Ruby Array. + def load_path=(load_path) + @@load_path = load_path + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/hash.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/hash.rb new file mode 100644 index 0000000..f2a2422 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/hash.rb @@ -0,0 +1,29 @@ +class Hash + def slice(*keep_keys) + h = {} + keep_keys.each { |key| h[key] = fetch(key) } + h + end unless Hash.method_defined?(:slice) + + def except(*less_keys) + slice(*keys - less_keys) + end unless Hash.method_defined?(:except) + + def deep_symbolize_keys + inject({}) { |result, (key, value)| + value = value.deep_symbolize_keys if value.is_a?(Hash) + result[(key.to_sym rescue key) || key] = value + result + } + end unless Hash.method_defined?(:deep_symbolize_keys) + + # deep_merge_hash! by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809 + MERGER = proc do |key, v1, v2| + Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2 + end + + def deep_merge!(data) + merge!(data, &MERGER) + end unless Hash.method_defined?(:deep_merge!) +end + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/kernel/surpress_warnings.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/kernel/surpress_warnings.rb new file mode 100644 index 0000000..cc03b1c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/kernel/surpress_warnings.rb @@ -0,0 +1,9 @@ +module Kernel + def suppress_warnings + original_verbosity = $VERBOSE + $VERBOSE = nil + result = yield + $VERBOSE = original_verbosity + result + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/string/interpolate.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/string/interpolate.rb new file mode 100644 index 0000000..56de8c0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/core_ext/string/interpolate.rb @@ -0,0 +1,105 @@ +# This backports the Ruby 1.9 String interpolation syntax to Ruby 1.8. +# +# This backport has been shipped with I18n for a number of versions. Meanwhile +# Rails has started to rely on it and we are going to move it to ActiveSupport. +# See https://rails.lighthouseapp.com/projects/8994/tickets/6013-move-19-string-interpolation-syntax-backport-from-i18n-to-activesupport +# +# Once the above patch has been applied to Rails the following code will be +# removed from I18n. + +=begin + heavily based on Masao Mutoh's gettext String interpolation extension + http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb + Copyright (C) 2005-2009 Masao Mutoh + You may redistribute it and/or modify it under the same license terms as Ruby. +=end + +begin + raise ArgumentError if ("a %{x}" % {:x=>'b'}) != 'a b' +rescue ArgumentError + # KeyError is raised by String#% when the string contains a named placeholder + # that is not contained in the given arguments hash. Ruby 1.9 includes and + # raises this exception natively. We define it to mimic Ruby 1.9's behaviour + # in Ruby 1.8.x + class KeyError < IndexError + def initialize(message = nil) + super(message || "key not found") + end + end unless defined?(KeyError) + + # Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError. + # + # String#% method which accept "named argument". The translator can know + # the meaning of the msgids using "named argument" instead of %s/%d style. + class String + # For older ruby versions, such as ruby-1.8.5 + alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'} + alias :interpolate_without_ruby_19_syntax :% # :nodoc: + + INTERPOLATION_PATTERN = Regexp.union( + /%\{(\w+)\}/, # matches placeholders like "%{foo}" + /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%.d" + ) + + INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union( + /%%/, + INTERPOLATION_PATTERN + ) + + # % uses self (i.e. the String) as a format specification and returns the + # result of applying it to the given arguments. In other words it interpolates + # the given arguments to the string according to the formats the string + # defines. + # + # There are three ways to use it: + # + # * Using a single argument or Array of arguments. + # + # This is the default behaviour of the String class. See Kernel#sprintf for + # more details about the format string. + # + # Example: + # + # "%d %s" % [1, "message"] + # # => "1 message" + # + # * Using a Hash as an argument and unformatted, named placeholders. + # + # When you pass a Hash as an argument and specify placeholders with %{foo} + # it will interpret the hash values as named arguments. + # + # Example: + # + # "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"} + # # => "Masao Mutoh" + # + # * Using a Hash as an argument and formatted, named placeholders. + # + # When you pass a Hash as an argument and specify placeholders with %d + # it will interpret the hash values as named arguments and format the value + # according to the formatting instruction appended to the closing >. + # + # Example: + # + # "%d, %.1f" % { :integer => 10, :float => 43.4 } + # # => "10, 43.3" + def %(args) + if args.kind_of?(Hash) + dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match| + if match == '%%' + '%' + else + key = ($1 || $2).to_sym + raise KeyError unless args.has_key?(key) + $3 ? sprintf("%#{$3}", args[key]) : args[key] + end + end + elsif self =~ INTERPOLATION_PATTERN + raise ArgumentError.new('one hash required') + else + result = gsub(/%([{<])/, '%%\1') + result.send :'interpolate_without_ruby_19_syntax', args + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/exceptions.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/exceptions.rb new file mode 100644 index 0000000..2f625a0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/exceptions.rb @@ -0,0 +1,106 @@ +module I18n + # Handles exceptions raised in the backend. All exceptions except for + # MissingTranslationData exceptions are re-thrown. When a MissingTranslationData + # was caught the handler returns an error message string containing the key/scope. + # Note that the exception handler is not called when the option :throw was given. + class ExceptionHandler + include Module.new { + def call(exception, locale, key, options) + if exception.is_a?(MissingTranslation) + options[:rescue_format] == :html ? exception.html_message : exception.message + elsif exception.is_a?(Exception) + raise exception + else + throw :exception, exception + end + end + } + end + + class ArgumentError < ::ArgumentError; end + + class InvalidLocale < ArgumentError + attr_reader :locale + def initialize(locale) + @locale = locale + super "#{locale.inspect} is not a valid locale" + end + end + + class InvalidLocaleData < ArgumentError + attr_reader :filename + def initialize(filename) + @filename = filename + super "can not load translations from #{filename}, expected it to return a hash, but does not" + end + end + + class MissingTranslation + module Base + attr_reader :locale, :key, :options + + def initialize(locale, key, options = nil) + @key, @locale, @options = key, locale, options.dup || {} + options.each { |k, v| self.options[k] = v.inspect if v.is_a?(Proc) } + end + + def html_message + key = keys.last.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize } + %(#{key}) + end + + def keys + @keys ||= I18n.normalize_keys(locale, key, options[:scope]).tap do |keys| + keys << 'no key' if keys.size < 2 + end + end + + def message + "translation missing: #{keys.join('.')}" + end + alias :to_s :message + + def to_exception + MissingTranslationData.new(locale, key, options) + end + end + + include Base + end + + class MissingTranslationData < ArgumentError + include MissingTranslation::Base + end + + class InvalidPluralizationData < ArgumentError + attr_reader :entry, :count + def initialize(entry, count) + @entry, @count = entry, count + super "translation data #{entry.inspect} can not be used with :count => #{count}" + end + end + + class MissingInterpolationArgument < ArgumentError + attr_reader :values, :string + def initialize(values, string) + @values, @string = values, string + super "missing interpolation argument in #{string.inspect} (#{values.inspect} given)" + end + end + + class ReservedInterpolationKey < ArgumentError + attr_reader :key, :string + def initialize(key, string) + @key, @string = key, string + super "reserved key #{key.inspect} used in #{string.inspect}" + end + end + + class UnknownFileType < ArgumentError + attr_reader :type, :filename + def initialize(type, filename) + @type, @filename = type, filename + super "can not load translations from #{filename}, the file type #{type} is not known" + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext.rb new file mode 100644 index 0000000..26a5d48 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext.rb @@ -0,0 +1,25 @@ +module I18n + module Gettext + PLURAL_SEPARATOR = "\001" + CONTEXT_SEPARATOR = "\004" + + autoload :Helpers, 'i18n/gettext/helpers' + + @@plural_keys = { :en => [:one, :other] } + + class << self + # returns an array of plural keys for the given locale so that we can + # convert from gettext's integer-index based style + # TODO move this information to the pluralization module + def plural_keys(locale) + @@plural_keys[locale] || @@plural_keys[:en] + end + + def extract_scope(msgid, separator) + scope = msgid.to_s.split(separator) + msgid = scope.pop + [scope, msgid] + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext/helpers.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext/helpers.rb new file mode 100644 index 0000000..ea07d05 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext/helpers.rb @@ -0,0 +1,64 @@ +require 'i18n/gettext' + +module I18n + module Gettext + # Implements classical Gettext style accessors. To use this include the + # module to the global namespace or wherever you want to use it. + # + # include I18n::Gettext::Helpers + module Helpers + def gettext(msgid, options = {}) + I18n.t(msgid, { :default => msgid, :separator => '|' }.merge(options)) + end + alias _ gettext + + def sgettext(msgid, separator = '|') + scope, msgid = I18n::Gettext.extract_scope(msgid, separator) + I18n.t(msgid, :scope => scope, :default => msgid, :separator => separator) + end + alias s_ sgettext + + def pgettext(msgctxt, msgid) + separator = I18n::Gettext::CONTEXT_SEPARATOR + sgettext([msgctxt, msgid].join(separator), separator) + end + alias p_ pgettext + + def ngettext(msgid, msgid_plural, n = 1) + nsgettext(msgid, msgid_plural, n) + end + alias n_ ngettext + + # Method signatures: + # nsgettext('Fruits|apple', 'apples', 2) + # nsgettext(['Fruits|apple', 'apples'], 2) + def nsgettext(msgid, msgid_plural, n = 1, separator = '|') + if msgid.is_a?(Array) + msgid, msgid_plural, n, separator = msgid[0], msgid[1], msgid_plural, n + separator = '|' unless separator.is_a?(::String) + end + + scope, msgid = I18n::Gettext.extract_scope(msgid, separator) + default = { :one => msgid, :other => msgid_plural } + I18n.t(msgid, :default => default, :count => n, :scope => scope, :separator => separator) + end + alias ns_ nsgettext + + # Method signatures: + # npgettext('Fruits', 'apple', 'apples', 2) + # npgettext('Fruits', ['apple', 'apples'], 2) + def npgettext(msgctxt, msgid, msgid_plural, n = 1) + separator = I18n::Gettext::CONTEXT_SEPARATOR + + if msgid.is_a?(Array) + msgid_plural, msgid, n = msgid[1], [msgctxt, msgid[0]].join(separator), msgid_plural + else + msgid = [msgctxt, msgid].join(separator) + end + + nsgettext(msgid, msgid_plural, n, separator) + end + alias np_ npgettext + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext/po_parser.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext/po_parser.rb new file mode 100644 index 0000000..547df6a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/gettext/po_parser.rb @@ -0,0 +1,329 @@ +=begin + poparser.rb - Generate a .mo + + Copyright (C) 2003-2009 Masao Mutoh + + You may redistribute it and/or modify it under the same + license terms as Ruby. +=end + +#MODIFIED +# removed include GetText etc +# added stub translation method _(x) +require 'racc/parser' + +module GetText + + class PoParser < Racc::Parser + + def _(x) + x + end + +module_eval <<'..end src/poparser.ry modeval..id7a99570e05', 'src/poparser.ry', 108 + def unescape(orig) + ret = orig.gsub(/\\n/, "\n") + ret.gsub!(/\\t/, "\t") + ret.gsub!(/\\r/, "\r") + ret.gsub!(/\\"/, "\"") + ret + end + + def parse(str, data, ignore_fuzzy = true) + @comments = [] + @data = data + @fuzzy = false + @msgctxt = "" + $ignore_fuzzy = ignore_fuzzy + + str.strip! + @q = [] + until str.empty? do + case str + when /\A\s+/ + str = $' + when /\Amsgctxt/ + @q.push [:MSGCTXT, $&] + str = $' + when /\Amsgid_plural/ + @q.push [:MSGID_PLURAL, $&] + str = $' + when /\Amsgid/ + @q.push [:MSGID, $&] + str = $' + when /\Amsgstr/ + @q.push [:MSGSTR, $&] + str = $' + when /\A\[(\d+)\]/ + @q.push [:PLURAL_NUM, $1] + str = $' + when /\A\#~(.*)/ + $stderr.print _("Warning: obsolete msgid exists.\n") + $stderr.print " #{$&}\n" + @q.push [:COMMENT, $&] + str = $' + when /\A\#(.*)/ + @q.push [:COMMENT, $&] + str = $' + when /\A\"(.*)\"/ + @q.push [:STRING, $1] + str = $' + else + #c = str[0,1] + #@q.push [:STRING, c] + str = str[1..-1] + end + end + @q.push [false, '$end'] + if $DEBUG + @q.each do |a,b| + puts "[#{a}, #{b}]" + end + end + @yydebug = true if $DEBUG + do_parse + + if @comments.size > 0 + @data.set_comment(:last, @comments.join("\n")) + end + @data + end + + def next_token + @q.shift + end + + def on_message(msgid, msgstr) + if msgstr.size > 0 + @data[msgid] = msgstr + @data.set_comment(msgid, @comments.join("\n")) + end + @comments.clear + @msgctxt = "" + end + + def on_comment(comment) + @fuzzy = true if (/fuzzy/ =~ comment) + @comments << comment + end + + +..end src/poparser.ry modeval..id7a99570e05 + +##### racc 1.4.5 generates ### + +racc_reduce_table = [ + 0, 0, :racc_error, + 0, 10, :_reduce_none, + 2, 10, :_reduce_none, + 2, 10, :_reduce_none, + 2, 10, :_reduce_none, + 2, 12, :_reduce_5, + 1, 13, :_reduce_none, + 1, 13, :_reduce_none, + 4, 15, :_reduce_8, + 5, 16, :_reduce_9, + 2, 17, :_reduce_10, + 1, 17, :_reduce_none, + 3, 18, :_reduce_12, + 1, 11, :_reduce_13, + 2, 14, :_reduce_14, + 1, 14, :_reduce_15 ] + +racc_reduce_n = 16 + +racc_shift_n = 26 + +racc_action_table = [ + 3, 13, 5, 7, 9, 15, 16, 17, 20, 17, + 13, 17, 13, 13, 11, 17, 23, 20, 13, 17 ] + +racc_action_check = [ + 1, 16, 1, 1, 1, 12, 12, 12, 18, 18, + 7, 14, 15, 9, 3, 19, 20, 21, 23, 25 ] + +racc_action_pointer = [ + nil, 0, nil, 14, nil, nil, nil, 3, nil, 6, + nil, nil, 0, nil, 4, 5, -6, nil, 2, 8, + 8, 11, nil, 11, nil, 12 ] + +racc_action_default = [ + -1, -16, -2, -16, -3, -13, -4, -16, -6, -16, + -7, 26, -16, -15, -5, -16, -16, -14, -16, -8, + -16, -9, -11, -16, -10, -12 ] + +racc_goto_table = [ + 12, 22, 14, 4, 24, 6, 2, 8, 18, 19, + 10, 21, 1, nil, nil, nil, 25 ] + +racc_goto_check = [ + 5, 9, 5, 3, 9, 4, 2, 6, 5, 5, + 7, 8, 1, nil, nil, nil, 5 ] + +racc_goto_pointer = [ + nil, 12, 5, 2, 4, -7, 6, 9, -7, -17 ] + +racc_goto_default = [ + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] + +racc_token_table = { + false => 0, + Object.new => 1, + :COMMENT => 2, + :MSGID => 3, + :MSGCTXT => 4, + :MSGID_PLURAL => 5, + :MSGSTR => 6, + :STRING => 7, + :PLURAL_NUM => 8 } + +racc_use_result_var = true + +racc_nt_base = 9 + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ +'$end', +'error', +'COMMENT', +'MSGID', +'MSGCTXT', +'MSGID_PLURAL', +'MSGSTR', +'STRING', +'PLURAL_NUM', +'$start', +'msgfmt', +'comment', +'msgctxt', +'message', +'string_list', +'single_message', +'plural_message', +'msgstr_plural', +'msgstr_plural_line'] + +Racc_debug_parser = true + +##### racc system variables end ##### + + # reduce 0 omitted + + # reduce 1 omitted + + # reduce 2 omitted + + # reduce 3 omitted + + # reduce 4 omitted + +module_eval <<'.,.,', 'src/poparser.ry', 25 + def _reduce_5( val, _values, result ) + @msgctxt = unescape(val[1]) + "\004" + result + end +.,., + + # reduce 6 omitted + + # reduce 7 omitted + +module_eval <<'.,.,', 'src/poparser.ry', 48 + def _reduce_8( val, _values, result ) + if @fuzzy and $ignore_fuzzy + if val[1] != "" + $stderr.print _("Warning: fuzzy message was ignored.\n") + $stderr.print " msgid '#{val[1]}'\n" + else + on_message('', unescape(val[3])) + end + @fuzzy = false + else + on_message(@msgctxt + unescape(val[1]), unescape(val[3])) + end + result = "" + result + end +.,., + +module_eval <<'.,.,', 'src/poparser.ry', 65 + def _reduce_9( val, _values, result ) + if @fuzzy and $ignore_fuzzy + if val[1] != "" + $stderr.print _("Warning: fuzzy message was ignored.\n") + $stderr.print "msgid = '#{val[1]}\n" + else + on_message('', unescape(val[3])) + end + @fuzzy = false + else + on_message(@msgctxt + unescape(val[1]) + "\000" + unescape(val[3]), unescape(val[4])) + end + result = "" + result + end +.,., + +module_eval <<'.,.,', 'src/poparser.ry', 76 + def _reduce_10( val, _values, result ) + if val[0].size > 0 + result = val[0] + "\000" + val[1] + else + result = "" + end + result + end +.,., + + # reduce 11 omitted + +module_eval <<'.,.,', 'src/poparser.ry', 84 + def _reduce_12( val, _values, result ) + result = val[2] + result + end +.,., + +module_eval <<'.,.,', 'src/poparser.ry', 91 + def _reduce_13( val, _values, result ) + on_comment(val[0]) + result + end +.,., + +module_eval <<'.,.,', 'src/poparser.ry', 99 + def _reduce_14( val, _values, result ) + result = val.delete_if{|item| item == ""}.join + result + end +.,., + +module_eval <<'.,.,', 'src/poparser.ry', 103 + def _reduce_15( val, _values, result ) + result = val[0] + result + end +.,., + + def _reduce_none( val, _values, result ) + result + end + + end # class PoParser + +end # module GetText diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/interpolate/ruby.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/interpolate/ruby.rb new file mode 100644 index 0000000..29b2814 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/interpolate/ruby.rb @@ -0,0 +1,31 @@ +# heavily based on Masao Mutoh's gettext String interpolation extension +# http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb + +module I18n + INTERPOLATION_PATTERN = Regexp.union( + /%%/, + /%\{(\w+)\}/, # matches placeholders like "%{foo}" + /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%.d" + ) + + class << self + def interpolate(string, values) + raise ReservedInterpolationKey.new($1.to_sym, string) if string =~ RESERVED_KEYS_PATTERN + raise ArgumentError.new('Interpolation values must be a Hash.') unless values.kind_of?(Hash) + interpolate_hash(string, values) + end + + def interpolate_hash(string, values) + string.gsub(INTERPOLATION_PATTERN) do |match| + if match == '%%' + '%' + else + key = ($1 || $2).to_sym + value = values.key?(key) ? values[key] : raise(MissingInterpolationArgument.new(values, string)) + value = value.call(values) if value.respond_to?(:call) + $3 ? sprintf("%#{$3}", value) : value + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale.rb new file mode 100644 index 0000000..4f9d026 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale.rb @@ -0,0 +1,6 @@ +module I18n + module Locale + autoload :Fallbacks, 'i18n/locale/fallbacks' + autoload :Tag, 'i18n/locale/tag' + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/fallbacks.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/fallbacks.rb new file mode 100644 index 0000000..589817c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/fallbacks.rb @@ -0,0 +1,96 @@ +# Locale Fallbacks +# +# Extends the I18n module to hold a fallbacks instance which is set to an +# instance of I18n::Locale::Fallbacks by default but can be swapped with a +# different implementation. +# +# Locale fallbacks will compute a number of fallback locales for a given locale. +# For example: +# +#
                        
                        +# I18n.fallbacks[:"es-MX"] # => [:"es-MX", :es, :en] 
                        +# +# Locale fallbacks always fall back to +# +# * all parent locales of a given locale (e.g. :es for :"es-MX") first, +# * the current default locales and all of their parents second +# +# The default locales are set to [I18n.default_locale] by default but can be +# set to something else. +# +# One can additionally add any number of additional fallback locales manually. +# These will be added before the default locales to the fallback chain. For +# example: +# +# # using the default locale as default fallback locale +# +# I18n.default_locale = :"en-US" +# I18n.fallbacks = I18n::Fallbacks.new(:"de-AT" => :"de-DE") +# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :"de-DE", :de, :"en-US", :en] +# +# # using a custom locale as default fallback locale +# +# I18n.fallbacks = I18n::Fallbacks.new(:"en-GB", :"de-AT" => :de, :"de-CH" => :de) +# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"en-GB", :en] +# I18n.fallbacks[:"de-CH"] # => [:"de-CH", :de, :"en-GB", :en] +# +# # mapping fallbacks to an existing instance +# +# # people speaking Catalan also speak Spanish as spoken in Spain +# fallbacks = I18n.fallbacks +# fallbacks.map(:ca => :"es-ES") +# fallbacks[:ca] # => [:ca, :"es-ES", :es, :"en-US", :en] +# +# # people speaking Arabian as spoken in Palestine also speak Hebrew as spoken in Israel +# fallbacks.map(:"ar-PS" => :"he-IL") +# fallbacks[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en] +# fallbacks[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en] +# +# # people speaking Sami as spoken in Finnland also speak Swedish and Finnish as spoken in Finnland +# fallbacks.map(:sms => [:"se-FI", :"fi-FI"]) +# fallbacks[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en] + +module I18n + module Locale + class Fallbacks < Hash + def initialize(*mappings) + @map = {} + map(mappings.pop) if mappings.last.is_a?(Hash) + self.defaults = mappings.empty? ? [I18n.default_locale.to_sym] : mappings + end + + def defaults=(defaults) + @defaults = defaults.map { |default| compute(default, false) }.flatten + end + attr_reader :defaults + + def [](locale) + raise InvalidLocale.new(locale) if locale.nil? + locale = locale.to_sym + super || store(locale, compute(locale)) + end + + def map(mappings) + mappings.each do |from, to| + from, to = from.to_sym, Array(to) + to.each do |_to| + @map[from] ||= [] + @map[from] << _to.to_sym + end + end + end + + protected + + def compute(tags, include_defaults = true) + result = Array(tags).collect do |tag| + tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym } + tags.each { |_tag| tags += compute(@map[_tag]) if @map[_tag] } + tags + end.flatten + result.push(*defaults) if include_defaults + result.uniq.compact + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag.rb new file mode 100644 index 0000000..a640b44 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag.rb @@ -0,0 +1,28 @@ +# encoding: utf-8 + +module I18n + module Locale + module Tag + autoload :Parents, 'i18n/locale/tag/parents' + autoload :Rfc4646, 'i18n/locale/tag/rfc4646' + autoload :Simple, 'i18n/locale/tag/simple' + + class << self + # Returns the current locale tag implementation. Defaults to +I18n::Locale::Tag::Simple+. + def implementation + @@implementation ||= Simple + end + + # Sets the current locale tag implementation. Use this to set a different locale tag implementation. + def implementation=(implementation) + @@implementation = implementation + end + + # Factory method for locale tags. Delegates to the current locale tag implementation. + def tag(tag) + implementation.tag(tag) + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/parents.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/parents.rb new file mode 100644 index 0000000..ec53060 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/parents.rb @@ -0,0 +1,22 @@ +module I18n + module Locale + module Tag + module Parents + def parent + @parent ||= begin + segs = to_a.compact + segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil + end + end + + def self_and_parents + @self_and_parents ||= [self] + parents + end + + def parents + @parents ||= ([parent] + (parent ? parent.parents : [])).compact + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/rfc4646.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/rfc4646.rb new file mode 100644 index 0000000..4ce4c75 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/rfc4646.rb @@ -0,0 +1,74 @@ +# RFC 4646/47 compliant Locale tag implementation that parses locale tags to +# subtags such as language, script, region, variant etc. +# +# For more information see by http://en.wikipedia.org/wiki/IETF_language_tag +# +# Rfc4646::Parser does not implement grandfathered tags. + +module I18n + module Locale + module Tag + RFC4646_SUBTAGS = [ :language, :script, :region, :variant, :extension, :privateuse, :grandfathered ] + RFC4646_FORMATS = { :language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase } + + class Rfc4646 < Struct.new(*RFC4646_SUBTAGS) + class << self + # Parses the given tag and returns a Tag instance if it is valid. + # Returns false if the given tag is not valid according to RFC 4646. + def tag(tag) + matches = parser.match(tag) + new(*matches) if matches + end + + def parser + @@parser ||= Rfc4646::Parser + end + + def parser=(parser) + @@parser = parser + end + end + + include Parents + + RFC4646_FORMATS.each do |name, format| + define_method(name) { self[name].send(format) unless self[name].nil? } + end + + def to_sym + to_s.to_sym + end + + def to_s + @tag ||= to_a.compact.join("-") + end + + def to_a + members.collect { |attr| self.send(attr) } + end + + module Parser + PATTERN = %r{\A(?: + ([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language + (?:-([a-z]{4}))? # script + (?:-([a-z]{2}|\d{3}))? # region + (?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant + (?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension + (?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag + (x(?:-[0-9a-z]{1,8})+)| # privateuse tag + /* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered + )\z}xi + + class << self + def match(tag) + c = PATTERN.match(tag.to_s).captures + c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here? + rescue + false + end + end + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/simple.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/simple.rb new file mode 100644 index 0000000..68642a1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/locale/tag/simple.rb @@ -0,0 +1,39 @@ +# Simple Locale tag implementation that computes subtags by simply splitting +# the locale tag at '-' occurences. +module I18n + module Locale + module Tag + class Simple + class << self + def tag(tag) + new(tag) + end + end + + include Parents + + attr_reader :tag + + def initialize(*tag) + @tag = tag.join('-').to_sym + end + + def subtags + @subtags = tag.to_s.split('-').map { |subtag| subtag.to_s } + end + + def to_sym + tag + end + + def to_s + tag.to_s + end + + def to_a + subtags + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests.rb new file mode 100644 index 0000000..554cdef --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests.rb @@ -0,0 +1,12 @@ +module I18n + module Tests + autoload :Basics, 'i18n/tests/basics' + autoload :Defaults, 'i18n/tests/defaults' + autoload :Interpolation, 'i18n/tests/interpolation' + autoload :Link, 'i18n/tests/link' + autoload :Localization, 'i18n/tests/localization' + autoload :Lookup, 'i18n/tests/lookup' + autoload :Pluralization, 'i18n/tests/pluralization' + autoload :Procs, 'i18n/tests/procs' + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/basics.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/basics.rb new file mode 100644 index 0000000..101e7c5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/basics.rb @@ -0,0 +1,54 @@ +module I18n + module Tests + module Basics + def teardown + I18n.available_locales = nil + end + + test "available_locales returns the locales stored to the backend by default" do + I18n.backend.store_translations('de', :foo => 'bar') + I18n.backend.store_translations('en', :foo => 'foo') + + assert I18n.available_locales.include?(:de) + assert I18n.available_locales.include?(:en) + end + + test "available_locales can be set to something else independently from the actual locale data" do + I18n.backend.store_translations('de', :foo => 'bar') + I18n.backend.store_translations('en', :foo => 'foo') + + I18n.available_locales = :foo + assert_equal [:foo], I18n.available_locales + + I18n.available_locales = [:foo, 'bar'] + assert_equal [:foo, :bar], I18n.available_locales + + I18n.available_locales = nil + assert I18n.available_locales.include?(:de) + assert I18n.available_locales.include?(:en) + end + + test "available_locales memoizes when set explicitely" do + I18n.backend.expects(:available_locales).never + I18n.available_locales = [:foo] + I18n.backend.store_translations('de', :bar => 'baz') + I18n.reload! + assert_equal [:foo], I18n.available_locales + end + + test "available_locales delegates to the backend when not set explicitely" do + I18n.backend.expects(:available_locales).twice + assert_equal I18n.available_locales, I18n.available_locales + end + + test "storing a nil value as a translation removes it from the available locale data" do + I18n.backend.store_translations(:en, :to_be_deleted => 'bar') + assert_equal 'bar', I18n.t(:to_be_deleted, :default => 'baz') + + I18n.cache_store.clear if I18n.respond_to?(:cache_store) && I18n.cache_store + I18n.backend.store_translations(:en, :to_be_deleted => nil) + assert_equal 'baz', I18n.t(:to_be_deleted, :default => 'baz') + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/defaults.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/defaults.rb new file mode 100644 index 0000000..081dcbd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/defaults.rb @@ -0,0 +1,40 @@ +# encoding: utf-8 + +module I18n + module Tests + module Defaults + def setup + super + I18n.backend.store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' }) + end + + test "defaults: given nil as a key it returns the given default" do + assert_equal 'default', I18n.t(nil, :default => 'default') + end + + test "defaults: given a symbol as a default it translates the symbol" do + assert_equal 'bar', I18n.t(nil, :default => :'foo.bar') + end + + test "defaults: given a symbol as a default and a scope it stays inside the scope when looking up the symbol" do + assert_equal 'bar', I18n.t(:missing, :default => :bar, :scope => :foo) + end + + test "defaults: given an array as a default it returns the first match" do + assert_equal 'bar', I18n.t(:does_not_exist, :default => [:does_not_exist_2, :'foo.bar']) + end + + test "defaults: given an array of missing keys it raises a MissingTranslationData exception" do + assert_raise I18n::MissingTranslationData do + I18n.t(:does_not_exist, :default => [:does_not_exist_2, :does_not_exist_3], :raise => true) + end + end + + test "defaults: using a custom scope separator" do + # data must have been stored using the custom separator when using the ActiveRecord backend + I18n.backend.store_translations(:en, { :foo => { :bar => 'bar' } }, { :separator => '|' }) + assert_equal 'bar', I18n.t(nil, :default => :'foo|bar', :separator => '|') + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/interpolation.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/interpolation.rb new file mode 100644 index 0000000..06613f2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/interpolation.rb @@ -0,0 +1,133 @@ +# encoding: utf-8 + +module I18n + module Tests + module Interpolation + # If no interpolation parameter is not given, I18n should not alter the string. + # This behavior is due to three reasons: + # + # * Checking interpolation keys in all strings hits performance, badly; + # + # * This allows us to retrieve untouched values through I18n. For example + # I could have a middleware that returns I18n lookup results in JSON + # to be processed through Javascript. Leaving the keys untouched allows + # the interpolation to happen at the javascript level; + # + # * Security concerns: if I allow users to translate a web site, they can + # insert %{} in messages causing the I18n lookup to fail in every request. + # + test "interpolation: given no values it does not alter the string" do + assert_equal 'Hi %{name}!', interpolate(:default => 'Hi %{name}!') + end + + test "interpolation: given values it interpolates them into the string" do + assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => 'David') + end + + test "interpolation: given a nil value it still interpolates it into the string" do + assert_equal 'Hi !', interpolate(:default => 'Hi %{name}!', :name => nil) + end + + test "interpolation: given a lambda as a value it calls it if the string contains the key" do + assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => lambda { |*args| 'David' }) + end + + test "interpolation: given a lambda as a value it does not call it if the string does not contain the key" do + assert_nothing_raised { interpolate(:default => 'Hi!', :name => lambda { |*args| raise 'fail' }) } + end + + test "interpolation: given values but missing a key it raises I18n::MissingInterpolationArgument" do + assert_raise(I18n::MissingInterpolationArgument) do + interpolate(:default => '%{foo}', :bar => 'bar') + end + end + + test "interpolation: it does not raise I18n::MissingInterpolationArgument for escaped variables" do + assert_nothing_raised(I18n::MissingInterpolationArgument) do + assert_equal 'Barr %{foo}', interpolate(:default => '%{bar} %%{foo}', :bar => 'Barr') + end + end + + test "interpolation: it does not change the original, stored translation string" do + I18n.backend.store_translations(:en, :interpolate => 'Hi %{name}!') + assert_equal 'Hi David!', interpolate(:interpolate, :name => 'David') + assert_equal 'Hi Yehuda!', interpolate(:interpolate, :name => 'Yehuda') + end + + test "interpolation: given the translation is in utf-8 it still works" do + assert_equal 'Häi David!', interpolate(:default => 'Häi %{name}!', :name => 'David') + end + + test "interpolation: given the value is in utf-8 it still works" do + assert_equal 'Hi ゆãã²ã‚!', interpolate(:default => 'Hi %{name}!', :name => 'ゆãã²ã‚') + end + + test "interpolation: given the translation and the value are in utf-8 it still works" do + assert_equal 'ã“ã‚“ã«ã¡ã¯ã€ã‚†ãã²ã‚ã•ã‚“!', interpolate(:default => 'ã“ã‚“ã«ã¡ã¯ã€%{name}ã•ã‚“!', :name => 'ゆãã²ã‚') + end + + if Kernel.const_defined?(:Encoding) + test "interpolation: given a euc-jp translation and a utf-8 value it raises Encoding::CompatibilityError" do + assert_raise(Encoding::CompatibilityError) do + interpolate(:default => euc_jp('ã“ã‚“ã«ã¡ã¯ã€%{name}ã•ã‚“!'), :name => 'ゆãã²ã‚') + end + end + + test "interpolation: given a utf-8 translation and a euc-jp value it raises Encoding::CompatibilityError" do + assert_raise(Encoding::CompatibilityError) do + interpolate(:default => 'ã“ã‚“ã«ã¡ã¯ã€%{name}ã•ã‚“!', :name => euc_jp('ゆãã²ã‚')) + end + end + + test "interpolation: ASCII strings in the backend should be encoded to UTF8 if interpolation options are in UTF8" do + I18n.backend.store_translations 'en', 'encoding' => ('%{who} let me go'.force_encoding("ASCII")) + result = I18n.t 'encoding', :who => "mÃ¥mmÃ¥ miÃ¥" + assert_equal Encoding::UTF_8, result.encoding + end + + test "interpolation: UTF8 strings in the backend are still returned as UTF8 with ASCII interpolation" do + I18n.backend.store_translations 'en', 'encoding' => 'mÃ¥mmÃ¥ miÃ¥ %{what}' + result = I18n.t 'encoding', :what => 'let me go'.force_encoding("ASCII") + assert_equal Encoding::UTF_8, result.encoding + end + + test "interpolation: UTF8 strings in the backend are still returned as UTF8 even with numbers interpolation" do + I18n.backend.store_translations 'en', 'encoding' => '%{count} times: mÃ¥mmÃ¥ miÃ¥' + result = I18n.t 'encoding', :count => 3 + assert_equal Encoding::UTF_8, result.encoding + end + end + + test "interpolation: given a translations containing a reserved key it raises I18n::ReservedInterpolationKey" do + assert_raise(I18n::ReservedInterpolationKey) { interpolate(:default => '%{default}', :foo => :bar) } + assert_raise(I18n::ReservedInterpolationKey) { interpolate(:default => '%{scope}', :foo => :bar) } + assert_raise(I18n::ReservedInterpolationKey) { interpolate(:default => '%{separator}', :foo => :bar) } + end + + protected + + def capture(stream) + begin + stream = stream.to_s + eval "$#{stream} = StringIO.new" + yield + result = eval("$#{stream}").string + ensure + eval("$#{stream} = #{stream.upcase}") + end + + result + end + + def euc_jp(string) + string.encode!(Encoding::EUC_JP) + end + + def interpolate(*args) + options = args.last.is_a?(Hash) ? args.pop : {} + key = args.pop + I18n.backend.translate('en', key, options) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/link.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/link.rb new file mode 100644 index 0000000..da84a2c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/link.rb @@ -0,0 +1,56 @@ +# encoding: utf-8 + +module I18n + module Tests + module Link + test "linked lookup: if a key resolves to a symbol it looks up the symbol" do + I18n.backend.store_translations 'en', { + :link => :linked, + :linked => 'linked' + } + assert_equal 'linked', I18n.backend.translate('en', :link) + end + + test "linked lookup: if a key resolves to a dot-separated symbol it looks up the symbol" do + I18n.backend.store_translations 'en', { + :link => :"foo.linked", + :foo => { :linked => 'linked' } + } + assert_equal('linked', I18n.backend.translate('en', :link)) + end + + test "linked lookup: if a dot-separated key resolves to a symbol it looks up the symbol" do + I18n.backend.store_translations 'en', { + :foo => { :link => :linked }, + :linked => 'linked' + } + assert_equal('linked', I18n.backend.translate('en', :'foo.link')) + end + + test "linked lookup: if a dot-separated key resolves to a dot-separated symbol it looks up the symbol" do + I18n.backend.store_translations 'en', { + :foo => { :link => :"bar.linked" }, + :bar => { :linked => 'linked' } + } + assert_equal('linked', I18n.backend.translate('en', :'foo.link')) + end + + test "linked lookup: links always refer to the absolute key" do + I18n.backend.store_translations 'en', { + :foo => { :link => :linked, :linked => 'linked in foo' }, + :linked => 'linked absolutely' + } + assert_equal 'linked absolutely', I18n.backend.translate('en', :link, :scope => :foo) + end + + test "linked lookup: a link can resolve to a namespace in the middle of a dot-separated key" do + I18n.backend.store_translations 'en', { + :activemodel => { :errors => { :messages => { :blank => "can't be blank" } } }, + :activerecord => { :errors => { :messages => :"activemodel.errors.messages" } } + } + assert_equal "can't be blank", I18n.t(:"activerecord.errors.messages.blank") + assert_equal "can't be blank", I18n.t(:"activerecord.errors.messages.blank") + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization.rb new file mode 100644 index 0000000..53b1502 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization.rb @@ -0,0 +1,19 @@ +module I18n + module Tests + module Localization + autoload :Date, 'i18n/tests/localization/date' + autoload :DateTime, 'i18n/tests/localization/date_time' + autoload :Time, 'i18n/tests/localization/time' + autoload :Procs, 'i18n/tests/localization/procs' + + def self.included(base) + base.class_eval do + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Procs + include I18n::Tests::Localization::Time + end + end + end + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/date.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/date.rb new file mode 100644 index 0000000..a866f90 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/date.rb @@ -0,0 +1,84 @@ +# encoding: utf-8 + +module I18n + module Tests + module Localization + module Date + def setup + super + setup_date_translations + @date = ::Date.new(2008, 3, 1) + end + + test "localize Date: given the short format it uses it" do + # TODO should be Mrz, shouldn't it? + assert_equal '01. Mar', I18n.l(@date, :format => :short, :locale => :de) + end + + test "localize Date: given the long format it uses it" do + assert_equal '01. März 2008', I18n.l(@date, :format => :long, :locale => :de) + end + + test "localize Date: given the default format it uses it" do + assert_equal '01.03.2008', I18n.l(@date, :format => :default, :locale => :de) + end + + test "localize Date: given a day name format it returns the correct day name" do + assert_equal 'Samstag', I18n.l(@date, :format => '%A', :locale => :de) + end + + test "localize Date: given an abbreviated day name format it returns the correct abbreviated day name" do + assert_equal 'Sa', I18n.l(@date, :format => '%a', :locale => :de) + end + + test "localize Date: given a month name format it returns the correct month name" do + assert_equal 'März', I18n.l(@date, :format => '%B', :locale => :de) + end + + test "localize Date: given an abbreviated month name format it returns the correct abbreviated month name" do + # TODO should be Mrz, shouldn't it? + assert_equal 'Mar', I18n.l(@date, :format => '%b', :locale => :de) + end + + test "localize Date: given an unknown format it does not fail" do + assert_nothing_raised { I18n.l(@date, :format => '%x') } + end + + test "localize Date: given nil it raises I18n::ArgumentError" do + assert_raise(I18n::ArgumentError) { I18n.l(nil) } + end + + test "localize Date: given a plain Object it raises I18n::ArgumentError" do + assert_raise(I18n::ArgumentError) { I18n.l(Object.new) } + end + + test "localize Date: given a format is missing it raises I18n::MissingTranslationData" do + assert_raise(I18n::MissingTranslationData) { I18n.l(@date, :format => :missing) } + end + + test "localize Date: it does not alter the format string" do + assert_equal '01. Februar 2009', I18n.l(::Date.parse('2009-02-01'), :format => :long, :locale => :de) + assert_equal '01. Oktober 2009', I18n.l(::Date.parse('2009-10-01'), :format => :long, :locale => :de) + end + + protected + + def setup_date_translations + I18n.backend.store_translations :de, { + :date => { + :formats => { + :default => "%d.%m.%Y", + :short => "%d. %b", + :long => "%d. %B %Y", + }, + :day_names => %w(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag), + :abbr_day_names => %w(So Mo Di Mi Do Fr Sa), + :month_names => %w(Januar Februar März April Mai Juni Juli August September Oktober November Dezember).unshift(nil), + :abbr_month_names => %w(Jan Feb Mar Apr Mai Jun Jul Aug Sep Okt Nov Dez).unshift(nil) + } + } + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/date_time.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/date_time.rb new file mode 100644 index 0000000..a926d1c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/date_time.rb @@ -0,0 +1,77 @@ +# encoding: utf-8 + +module I18n + module Tests + module Localization + module DateTime + def setup + super + setup_datetime_translations + @datetime = ::DateTime.new(2008, 3, 1, 6) + @other_datetime = ::DateTime.new(2008, 3, 1, 18) + end + + test "localize DateTime: given the short format it uses it" do + # TODO should be Mrz, shouldn't it? + assert_equal '01. Mar 06:00', I18n.l(@datetime, :format => :short, :locale => :de) + end + + test "localize DateTime: given the long format it uses it" do + assert_equal '01. März 2008 06:00', I18n.l(@datetime, :format => :long, :locale => :de) + end + + test "localize DateTime: given the default format it uses it" do + # TODO should be Mrz, shouldn't it? + assert_equal 'Sa, 01. Mar 2008 06:00:00 +0000', I18n.l(@datetime, :format => :default, :locale => :de) + end + + test "localize DateTime: given a day name format it returns the correct day name" do + assert_equal 'Samstag', I18n.l(@datetime, :format => '%A', :locale => :de) + end + + test "localize DateTime: given an abbreviated day name format it returns the correct abbreviated day name" do + assert_equal 'Sa', I18n.l(@datetime, :format => '%a', :locale => :de) + end + + test "localize DateTime: given a month name format it returns the correct month name" do + assert_equal 'März', I18n.l(@datetime, :format => '%B', :locale => :de) + end + + test "localize DateTime: given an abbreviated month name format it returns the correct abbreviated month name" do + # TODO should be Mrz, shouldn't it? + assert_equal 'Mar', I18n.l(@datetime, :format => '%b', :locale => :de) + end + + test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator" do + assert_equal 'am', I18n.l(@datetime, :format => '%p', :locale => :de) + assert_equal 'pm', I18n.l(@other_datetime, :format => '%p', :locale => :de) + end + + test "localize DateTime: given an unknown format it does not fail" do + assert_nothing_raised { I18n.l(@datetime, :format => '%x') } + end + + test "localize DateTime: given a format is missing it raises I18n::MissingTranslationData" do + assert_raise(I18n::MissingTranslationData) { I18n.l(@datetime, :format => :missing) } + end + + protected + + def setup_datetime_translations + # time translations might have been set up in Tests::Api::Localization::Time + I18n.backend.store_translations :de, { + :time => { + :formats => { + :default => "%a, %d. %b %Y %H:%M:%S %z", + :short => "%d. %b %H:%M", + :long => "%d. %B %Y %H:%M" + }, + :am => 'am', + :pm => 'pm' + } + } + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/procs.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/procs.rb new file mode 100644 index 0000000..83d24bc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/procs.rb @@ -0,0 +1,116 @@ +# encoding: utf-8 + +module I18n + module Tests + module Localization + module Procs + test "localize: using day names from lambdas" do + setup_time_proc_translations + time = ::Time.utc(2008, 3, 1, 6, 0) + assert_match(/Суббота/, I18n.l(time, :format => "%A, %d %B", :locale => :ru)) + assert_match(/Ñуббота/, I18n.l(time, :format => "%d %B (%A)", :locale => :ru)) + end + + test "localize: using month names from lambdas" do + setup_time_proc_translations + time = ::Time.utc(2008, 3, 1, 6, 0) + assert_match(/марта/, I18n.l(time, :format => "%d %B %Y", :locale => :ru)) + assert_match(/Март /, I18n.l(time, :format => "%B %Y", :locale => :ru)) + end + + test "localize: using abbreviated day names from lambdas" do + setup_time_proc_translations + time = ::Time.utc(2008, 3, 1, 6, 0) + assert_match(/марта/, I18n.l(time, :format => "%d %b %Y", :locale => :ru)) + assert_match(/март /, I18n.l(time, :format => "%b %Y", :locale => :ru)) + end + + test "localize Date: given a format that resolves to a Proc it calls the Proc with the object" do + setup_time_proc_translations + date = ::Date.new(2008, 3, 1, 6) + assert_equal '[Sat, 01 Mar 2008, {}]', I18n.l(date, :format => :proc, :locale => :ru) + end + + test "localize Date: given a format that resolves to a Proc it calls the Proc with the object and extra options" do + setup_time_proc_translations + date = ::Date.new(2008, 3, 1, 6) + assert_equal '[Sat, 01 Mar 2008, {:foo=>"foo"}]', I18n.l(date, :format => :proc, :foo => 'foo', :locale => :ru) + end + + test "localize DateTime: given a format that resolves to a Proc it calls the Proc with the object" do + setup_time_proc_translations + datetime = ::DateTime.new(2008, 3, 1, 6) + assert_equal '[Sat, 01 Mar 2008 06:00:00 +00:00, {}]', I18n.l(datetime, :format => :proc, :locale => :ru) + end + + test "localize DateTime: given a format that resolves to a Proc it calls the Proc with the object and extra options" do + setup_time_proc_translations + datetime = ::DateTime.new(2008, 3, 1, 6) + assert_equal '[Sat, 01 Mar 2008 06:00:00 +00:00, {:foo=>"foo"}]', I18n.l(datetime, :format => :proc, :foo => 'foo', :locale => :ru) + end + + test "localize Time: given a format that resolves to a Proc it calls the Proc with the object" do + setup_time_proc_translations + time = ::Time.utc(2008, 3, 1, 6, 0) + assert_equal inspect_args([time, {}]), I18n.l(time, :format => :proc, :locale => :ru) + end + + test "localize Time: given a format that resolves to a Proc it calls the Proc with the object and extra options" do + setup_time_proc_translations + time = ::Time.utc(2008, 3, 1, 6, 0) + options = { :foo => 'foo' } + assert_equal inspect_args([time, options]), I18n.l(time, options.merge(:format => :proc, :locale => :ru)) + end + + protected + + def inspect_args(args) + args = args.map do |arg| + case arg + when ::Time, ::DateTime + arg.strftime('%a, %d %b %Y %H:%M:%S %Z').sub('+0000', '+00:00') + when ::Date + arg.strftime('%a, %d %b %Y') + when Hash + arg.delete(:fallback) + arg.inspect + else + arg.inspect + end + end + "[#{args.join(', ')}]" + end + + def setup_time_proc_translations + I18n.backend.store_translations :ru, { + :time => { + :formats => { + :proc => lambda { |*args| inspect_args(args) } + } + }, + :date => { + :formats => { + :proc => lambda { |*args| inspect_args(args) } + }, + :'day_names' => lambda { |key, options| + (options[:format] =~ /^%A/) ? + %w(ВоÑкреÑенье Понедельник Вторник Среда Четверг ПÑтница Суббота) : + %w(воÑкреÑенье понедельник вторник Ñреда четверг пÑтница Ñуббота) + }, + :'month_names' => lambda { |key, options| + (options[:format] =~ /(%d|%e)(\s*)?(%B)/) ? + %w(ÑÐ½Ð²Ð°Ñ€Ñ Ñ„ÐµÐ²Ñ€Ð°Ð»Ñ Ð¼Ð°Ñ€Ñ‚Ð° Ð°Ð¿Ñ€ÐµÐ»Ñ Ð¼Ð°Ñ Ð¸ÑŽÐ½Ñ Ð¸ÑŽÐ»Ñ Ð°Ð²Ð³ÑƒÑта ÑентÑÐ±Ñ€Ñ Ð¾ÐºÑ‚ÑÐ±Ñ€Ñ Ð½Ð¾ÑÐ±Ñ€Ñ Ð´ÐµÐºÐ°Ð±Ñ€Ñ).unshift(nil) : + %w(Январь Февраль Март Ðпрель Май Июнь Июль ÐвгуÑÑ‚ СентÑбрь ОктÑбрь ÐоÑбрь Декабрь).unshift(nil) + }, + :'abbr_month_names' => lambda { |key, options| + (options[:format] =~ /(%d|%e)(\s*)(%b)/) ? + %w(Ñнв. февр. марта апр. Ð¼Ð°Ñ Ð¸ÑŽÐ½Ñ Ð¸ÑŽÐ»Ñ Ð°Ð²Ð³. Ñент. окт. ноÑб. дек.).unshift(nil) : + %w(Ñнв. февр. март апр. май июнь июль авг. Ñент. окт. ноÑб. дек.).unshift(nil) + }, + } + } + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/time.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/time.rb new file mode 100644 index 0000000..599f21f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/localization/time.rb @@ -0,0 +1,76 @@ +# encoding: utf-8 + +module I18n + module Tests + module Localization + module Time + def setup + super + setup_time_translations + @time = ::Time.utc(2008, 3, 1, 6, 0) + @other_time = ::Time.utc(2008, 3, 1, 18, 0) + end + + test "localize Time: given the short format it uses it" do + # TODO should be Mrz, shouldn't it? + assert_equal '01. Mar 06:00', I18n.l(@time, :format => :short, :locale => :de) + end + + test "localize Time: given the long format it uses it" do + assert_equal '01. März 2008 06:00', I18n.l(@time, :format => :long, :locale => :de) + end + + # TODO Seems to break on Windows because ENV['TZ'] is ignored. What's a better way to do this? + # def test_localize_given_the_default_format_it_uses_it + # assert_equal 'Sa, 01. Mar 2008 06:00:00 +0000', I18n.l(@time, :format => :default, :locale => :de) + # end + + test "localize Time: given a day name format it returns the correct day name" do + assert_equal 'Samstag', I18n.l(@time, :format => '%A', :locale => :de) + end + + test "localize Time: given an abbreviated day name format it returns the correct abbreviated day name" do + assert_equal 'Sa', I18n.l(@time, :format => '%a', :locale => :de) + end + + test "localize Time: given a month name format it returns the correct month name" do + assert_equal 'März', I18n.l(@time, :format => '%B', :locale => :de) + end + + test "localize Time: given an abbreviated month name format it returns the correct abbreviated month name" do + # TODO should be Mrz, shouldn't it? + assert_equal 'Mar', I18n.l(@time, :format => '%b', :locale => :de) + end + + test "localize Time: given a meridian indicator format it returns the correct meridian indicator" do + assert_equal 'am', I18n.l(@time, :format => '%p', :locale => :de) + assert_equal 'pm', I18n.l(@other_time, :format => '%p', :locale => :de) + end + + test "localize Time: given an unknown format it does not fail" do + assert_nothing_raised { I18n.l(@time, :format => '%x') } + end + + test "localize Time: given a format is missing it raises I18n::MissingTranslationData" do + assert_raise(I18n::MissingTranslationData) { I18n.l(@time, :format => :missing) } + end + + protected + + def setup_time_translations + I18n.backend.store_translations :de, { + :time => { + :formats => { + :default => "%a, %d. %b %Y %H:%M:%S %z", + :short => "%d. %b %H:%M", + :long => "%d. %B %Y %H:%M", + }, + :am => 'am', + :pm => 'pm' + } + } + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/lookup.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/lookup.rb new file mode 100644 index 0000000..63c21ac --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/lookup.rb @@ -0,0 +1,74 @@ +# encoding: utf-8 + +module I18n + module Tests + module Lookup + def setup + super + I18n.backend.store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' }, :falsy => false, :truthy => true, + :string => "a", :array => %w(a b c), :hash => { "a" => "b" }) + end + + test "lookup: it returns a string" do + assert_equal("a", I18n.t(:string)) + end + + test "lookup: it returns hash" do + assert_equal({ :a => "b" }, I18n.t(:hash)) + end + + test "lookup: it returns a array" do + assert_equal(%w(a b c), I18n.t(:array)) + end + + test "lookup: it returns a native true" do + assert I18n.t(:truthy) === true + end + + test "lookup: it returns a native false" do + assert I18n.t(:falsy) === false + end + + test "lookup: given a missing key, no default and no raise option it returns an error message" do + assert_equal "translation missing: en.missing", I18n.t(:missing) + end + + test "lookup: given a missing key, no default and the raise option it raises MissingTranslationData" do + assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) } + end + + test "lookup: does not raise an exception if no translation data is present for the given locale" do + assert_nothing_raised { I18n.t(:foo, :locale => :xx) } + end + + test "lookup: given an array of keys it translates all of them" do + assert_equal %w(bar baz), I18n.t([:bar, :baz], :scope => [:foo]) + end + + test "lookup: using a custom scope separator" do + # data must have been stored using the custom separator when using the ActiveRecord backend + I18n.backend.store_translations(:en, { :foo => { :bar => 'bar' } }, { :separator => '|' }) + assert_equal 'bar', I18n.t('foo|bar', :separator => '|') + end + + # In fact it probably *should* fail but Rails currently relies on using the default locale instead. + # So we'll stick to this for now until we get it fixed in Rails. + test "lookup: given nil as a locale it does not raise but use the default locale" do + # assert_raise(I18n::InvalidLocale) { I18n.t(:bar, :locale => nil) } + assert_nothing_raised { I18n.t(:bar, :locale => nil) } + end + + test "lookup: a resulting String is not frozen" do + assert !I18n.t(:string).frozen? + end + + test "lookup: a resulting Array is not frozen" do + assert !I18n.t(:array).frozen? + end + + test "lookup: a resulting Hash is not frozen" do + assert !I18n.t(:hash).frozen? + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/pluralization.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/pluralization.rb new file mode 100644 index 0000000..d3319dc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/pluralization.rb @@ -0,0 +1,35 @@ +# encoding: utf-8 + +module I18n + module Tests + module Pluralization + test "pluralization: given 0 it returns the :zero translation if it is defined" do + assert_equal 'zero', I18n.t(:default => { :zero => 'zero' }, :count => 0) + end + + test "pluralization: given 0 it returns the :other translation if :zero is not defined" do + assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 0) + end + + test "pluralization: given 1 it returns the singular translation" do + assert_equal 'bar', I18n.t(:default => { :one => 'bar' }, :count => 1) + end + + test "pluralization: given 2 it returns the :other translation" do + assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 2) + end + + test "pluralization: given 3 it returns the :other translation" do + assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 3) + end + + test "pluralization: given nil it returns the whole entry" do + assert_equal({ :one => 'bar' }, I18n.t(:default => { :one => 'bar' }, :count => nil)) + end + + test "pluralization: given incomplete pluralization data it raises I18n::InvalidPluralizationData" do + assert_raise(I18n::InvalidPluralizationData) { I18n.t(:default => { :one => 'bar' }, :count => 2) } + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/procs.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/procs.rb new file mode 100644 index 0000000..55ff952 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/tests/procs.rb @@ -0,0 +1,55 @@ +# encoding: utf-8 + +module I18n + module Tests + module Procs + test "lookup: given a translation is a proc it calls the proc with the key and interpolation values" do + I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| filter_args(*args) }) + assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo') + end + + test "defaults: given a default is a Proc it calls it with the key and interpolation values" do + proc = lambda { |*args| filter_args(*args) } + assert_equal '[nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo') + end + + test "defaults: given a default is a key that resolves to a Proc it calls it with the key and interpolation values" do + I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| filter_args(*args) }) + assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(nil, :default => :a_lambda, :foo => 'foo') + assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(nil, :default => [nil, :a_lambda], :foo => 'foo') + end + + test "interpolation: given an interpolation value is a lambda it calls it with key and values before interpolating it" do + proc = lambda { |*args| filter_args(*args) } + assert_match %r(\[\{:foo=>#\}\]), I18n.t(nil, :default => '%{foo}', :foo => proc) + end + + test "interpolation: given a key resolves to a Proc that returns a string then interpolation still works" do + proc = lambda { |*args| "%{foo}: " + filter_args(*args) } + assert_equal 'foo: [nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo') + end + + test "pluralization: given a key resolves to a Proc that returns valid data then pluralization still works" do + proc = lambda { |*args| { :zero => 'zero', :one => 'one', :other => 'other' } } + assert_equal 'zero', I18n.t(:default => proc, :count => 0) + assert_equal 'one', I18n.t(:default => proc, :count => 1) + assert_equal 'other', I18n.t(:default => proc, :count => 2) + end + + test "lookup: given the option :resolve => false was passed it does not resolve proc translations" do + I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| filter_args(*args) }) + assert_equal Proc, I18n.t(:a_lambda, :resolve => false).class + end + + test "lookup: given the option :resolve => false was passed it does not resolve proc default" do + assert_equal Proc, I18n.t(nil, :default => lambda { |*args| filter_args(*args) }, :resolve => false).class + end + + protected + + def filter_args(*args) + args.map {|arg| arg.delete(:fallback) if arg.is_a?(Hash) ; arg }.inspect + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/version.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/version.rb new file mode 100644 index 0000000..8e9db4f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/lib/i18n/version.rb @@ -0,0 +1,3 @@ +module I18n + VERSION = "0.6.0" +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/all.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/all.rb new file mode 100644 index 0000000..e846143 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/all.rb @@ -0,0 +1,8 @@ +# encoding: utf-8 + +dir = File.dirname(__FILE__) +$LOAD_PATH.unshift(dir) + +Dir["#{dir}/**/*_test.rb"].sort.each do |file| + require file.sub(/^#{dir}\/(.*)\.rb$/, '\1') +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/all_features_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/all_features_test.rb new file mode 100644 index 0000000..74589b7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/all_features_test.rb @@ -0,0 +1,58 @@ +require 'test_helper' + +begin + require 'rubygems' + require 'active_support' +rescue LoadError + puts "not testing with Cache enabled because active_support can not be found" +end + +class I18nAllFeaturesApiTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Metadata + include I18n::Backend::Cache + include I18n::Backend::Cascade + include I18n::Backend::Fallbacks + include I18n::Backend::Pluralization + include I18n::Backend::Memoize + end + + def setup + I18n.backend = I18n::Backend::Chain.new(Backend.new, I18n::Backend::Simple.new) + I18n.cache_store = cache_store + super + end + + def teardown + I18n.cache_store.clear if I18n.cache_store + I18n.cache_store = nil + super + end + + def cache_store + ActiveSupport::Cache.lookup_store(:memory_store) if cache_available? + end + + def cache_available? + defined?(ActiveSupport) && defined?(ActiveSupport::Cache) + end + + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + test "make sure we use a Chain backend with an all features backend" do + assert_equal I18n::Backend::Chain, I18n.backend.class + assert_equal Backend, I18n.backend.backends.first.class + end + + # links: test that keys stored on one backend can link to keys stored on another backend +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/cascade_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/cascade_test.rb new file mode 100644 index 0000000..a40587b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/cascade_test.rb @@ -0,0 +1,28 @@ +require 'test_helper' + +class I18nCascadeApiTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Cascade + end + + def setup + I18n.backend = Backend.new + super + end + + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + test "make sure we use a backend with Cascade included" do + assert_equal Backend, I18n.backend.class + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/chain_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/chain_test.rb new file mode 100644 index 0000000..0a61cb0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/chain_test.rb @@ -0,0 +1,24 @@ +require 'test_helper' + +class I18nApiChainTest < Test::Unit::TestCase + def setup + super + I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend) + end + + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + test "make sure we use the Chain backend" do + assert_equal I18n::Backend::Chain, I18n.backend.class + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/fallbacks_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/fallbacks_test.rb new file mode 100644 index 0000000..31ebb00 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/fallbacks_test.rb @@ -0,0 +1,30 @@ +require 'test_helper' + +class I18nFallbacksApiTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Fallbacks + end + + def setup + I18n.backend = Backend.new + super + end + + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + test "make sure we use a backend with Fallbacks included" do + assert_equal Backend, I18n.backend.class + end + + # links: test that keys stored on one backend can link to keys stored on another backend +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/key_value_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/key_value_test.rb new file mode 100644 index 0000000..976ca6b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/key_value_test.rb @@ -0,0 +1,28 @@ +require 'test_helper' + +I18n::Tests.setup_rufus_tokyo + +class I18nKeyValueApiTest < Test::Unit::TestCase + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + # include Tests::Api::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + # include Tests::Api::Localization::Procs + + STORE = Rufus::Tokyo::Cabinet.new('*') + + def setup + I18n.backend = I18n::Backend::KeyValue.new(STORE) + super + end + + test "make sure we use the KeyValue backend" do + assert_equal I18n::Backend::KeyValue, I18n.backend.class + end +end if defined?(Rufus::Tokyo::Cabinet) diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/memoize_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/memoize_test.rb new file mode 100644 index 0000000..8839ec8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/memoize_test.rb @@ -0,0 +1,60 @@ +require 'test_helper' + +class I18nMemoizeBackendWithSimpleApiTest < Test::Unit::TestCase + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + class MemoizeBackend < I18n::Backend::Simple + include I18n::Backend::Memoize + end + + def setup + I18n.backend = MemoizeBackend.new + super + end + + test "make sure we use the MemoizeBackend backend" do + assert_equal MemoizeBackend, I18n.backend.class + end +end + +I18n::Tests.setup_rufus_tokyo + +class I18nMemoizeBackendWithKeyValueApiTest < Test::Unit::TestCase + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + + # include I18n::Tests::Procs + # include I18n::Tests::Localization::Procs + + class MemoizeBackend < I18n::Backend::KeyValue + include I18n::Backend::Memoize + end + + STORE = Rufus::Tokyo::Cabinet.new('*') + + def setup + I18n.backend = MemoizeBackend.new(STORE) + super + end + + test "make sure we use the MemoizeBackend backend" do + assert_equal MemoizeBackend, I18n.backend.class + end +end if defined?(Rufus::Tokyo::Cabinet) diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/pluralization_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/pluralization_test.rb new file mode 100644 index 0000000..5da3a5e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/pluralization_test.rb @@ -0,0 +1,30 @@ +require 'test_helper' + +class I18nPluralizationApiTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Pluralization + end + + def setup + I18n.backend = Backend.new + super + end + + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + test "make sure we use a backend with Pluralization included" do + assert_equal Backend, I18n.backend.class + end + + # links: test that keys stored on one backend can link to keys stored on another backend +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/simple_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/simple_test.rb new file mode 100644 index 0000000..02d6205 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/api/simple_test.rb @@ -0,0 +1,28 @@ +require 'test_helper' + +class I18nSimpleBackendApiTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Pluralization + end + + def setup + I18n.backend = I18n::Backend::Simple.new + super + end + + include I18n::Tests::Basics + include I18n::Tests::Defaults + include I18n::Tests::Interpolation + include I18n::Tests::Link + include I18n::Tests::Lookup + include I18n::Tests::Pluralization + include I18n::Tests::Procs + include I18n::Tests::Localization::Date + include I18n::Tests::Localization::DateTime + include I18n::Tests::Localization::Time + include I18n::Tests::Localization::Procs + + test "make sure we use the Simple backend" do + assert_equal I18n::Backend::Simple, I18n.backend.class + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/cache_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/cache_test.rb new file mode 100644 index 0000000..39df10d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/cache_test.rb @@ -0,0 +1,85 @@ +require 'test_helper' + +begin + require 'active_support' +rescue LoadError + $stderr.puts "Skipping cache tests using ActiveSupport" +else + +class I18nBackendCacheTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Cache + end + + def setup + I18n.backend = Backend.new + super + I18n.cache_store = ActiveSupport::Cache.lookup_store(:memory_store) + end + + def teardown + I18n.cache_store = nil + end + + test "it uses the cache" do + assert I18n.cache_store.is_a?(ActiveSupport::Cache::MemoryStore) + end + + test "translate hits the backend and caches the response" do + I18n.backend.expects(:lookup).returns('Foo') + assert_equal 'Foo', I18n.t(:foo) + + I18n.backend.expects(:lookup).never + assert_equal 'Foo', I18n.t(:foo) + + I18n.backend.expects(:lookup).returns('Bar') + assert_equal 'Bar', I18n.t(:bar) + end + + test "still raises MissingTranslationData but also caches it" do + assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) } + assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) } + assert_equal 1, I18n.cache_store.instance_variable_get(:@data).size + + # I18n.backend.expects(:lookup).returns(nil) + # assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) } + # I18n.backend.expects(:lookup).never + # assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) } + end + + test "uses 'i18n' as a cache key namespace by default" do + assert_equal 0, I18n.backend.send(:cache_key, :en, :foo, {}).index('i18n') + end + + test "adds a custom cache key namespace" do + with_cache_namespace('bar') do + assert_equal 0, I18n.backend.send(:cache_key, :en, :foo, {}).index('i18n/bar/') + end + end + + test "adds locale and hash of key and hash of options" do + options = { :bar=>1 } + options_hash = I18n::Backend::Cache::USE_INSPECT_HASH ? options.inspect.hash : options.hash + assert_equal "i18n//en/#{:foo.hash}/#{options_hash}", I18n.backend.send(:cache_key, :en, :foo, options) + end + + test "keys should not be equal" do + interpolation_values1 = { :foo => 1, :bar => 2 } + interpolation_values2 = { :foo => 2, :bar => 1 } + + key1 = I18n.backend.send(:cache_key, :en, :some_key, interpolation_values1) + key2 = I18n.backend.send(:cache_key, :en, :some_key, interpolation_values2) + + assert key1 != key2 + end + + protected + + def with_cache_namespace(namespace) + I18n.cache_namespace = namespace + yield + I18n.cache_namespace = nil + end +end + +end # AS cache check diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/cascade_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/cascade_test.rb new file mode 100644 index 0000000..c23f167 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/cascade_test.rb @@ -0,0 +1,85 @@ +require 'test_helper' + +class I18nBackendCascadeTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Cascade + end + + def setup + I18n.backend = Backend.new + store_translations(:en, :foo => 'foo', :bar => { :baz => 'baz' }) + @cascade_options = { :step => 1, :offset => 1, :skip_root => false } + end + + def lookup(key, options = {}) + I18n.t(key, options.merge(:cascade => @cascade_options)) + end + + test "still returns an existing translation as usual" do + assert_equal 'foo', lookup(:foo) + assert_equal 'baz', lookup(:'bar.baz') + end + + test "falls back by cutting keys off the end of the scope" do + assert_equal 'foo', lookup(:foo, :scope => :'missing') + assert_equal 'foo', lookup(:foo, :scope => :'missing.missing') + assert_equal 'baz', lookup(:baz, :scope => :'bar.missing') + assert_equal 'baz', lookup(:baz, :scope => :'bar.missing.missing') + end + + test "raises I18n::MissingTranslationData exception when no translation was found" do + assert_raise(I18n::MissingTranslationData) { lookup(:'foo.missing', :raise => true) } + assert_raise(I18n::MissingTranslationData) { lookup(:'bar.baz.missing', :raise => true) } + assert_raise(I18n::MissingTranslationData) { lookup(:'missing.bar.baz', :raise => true) } + end + + test "cascades before evaluating the default" do + assert_equal 'foo', lookup(:foo, :scope => :missing, :default => 'default') + end + + test "cascades defaults, too" do + assert_equal 'foo', lookup(nil, :default => [:'missing.missing', :'missing.foo']) + end + + test "works with :offset => 2 and a single key" do + @cascade_options[:offset] = 2 + lookup(:foo) + end + + test "assemble required fallbacks for ActiveRecord validation messages" do + store_translations(:en, + :errors => { + :odd => 'errors.odd', + :reply => { :title => { :blank => 'errors.reply.title.blank' }, :taken => 'errors.reply.taken' }, + :topic => { :title => { :format => 'errors.topic.title.format' }, :length => 'errors.topic.length' } + } + ) + assert_equal 'errors.reply.title.blank', lookup(:'errors.reply.title.blank', :default => :'errors.topic.title.blank') + assert_equal 'errors.reply.taken', lookup(:'errors.reply.title.taken', :default => :'errors.topic.title.taken') + assert_equal 'errors.topic.title.format', lookup(:'errors.reply.title.format', :default => :'errors.topic.title.format') + assert_equal 'errors.topic.length', lookup(:'errors.reply.title.length', :default => :'errors.topic.title.length') + assert_equal 'errors.odd', lookup(:'errors.reply.title.odd', :default => :'errors.topic.title.odd') + end + + test "assemble action view translation helper lookup cascade" do + @cascade_options[:offset] = 2 + + store_translations(:en, + :menu => { :show => 'menu.show' }, + :namespace => { + :menu => { :new => 'namespace.menu.new' }, + :controller => { + :menu => { :edit => 'namespace.controller.menu.edit' }, + :action => { + :menu => { :destroy => 'namespace.controller.action.menu.destroy' } + } + } + } + ) + + assert_equal 'menu.show', lookup(:'namespace.controller.action.menu.show') + assert_equal 'namespace.menu.new', lookup(:'namespace.controller.action.menu.new') + assert_equal 'namespace.controller.menu.edit', lookup(:'namespace.controller.action.menu.edit') + assert_equal 'namespace.controller.action.menu.destroy', lookup(:'namespace.controller.action.menu.destroy') + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/chain_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/chain_test.rb new file mode 100644 index 0000000..fc76ed4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/chain_test.rb @@ -0,0 +1,72 @@ +require 'test_helper' + +class I18nBackendChainTest < Test::Unit::TestCase + def setup + @first = backend(:en => { + :foo => 'Foo', :formats => { :short => 'short' }, :plural_1 => { :one => '%{count}' } + }) + @second = backend(:en => { + :bar => 'Bar', :formats => { :long => 'long' }, :plural_2 => { :one => 'one' } + }) + @chain = I18n.backend = I18n::Backend::Chain.new(@first, @second) + end + + test "looks up translations from the first chained backend" do + assert_equal 'Foo', @first.send(:translations)[:en][:foo] + assert_equal 'Foo', I18n.t(:foo) + end + + test "looks up translations from the second chained backend" do + assert_equal 'Bar', @second.send(:translations)[:en][:bar] + assert_equal 'Bar', I18n.t(:bar) + end + + test "defaults only apply to lookups on the last backend in the chain" do + assert_equal 'Foo', I18n.t(:foo, :default => 'Bah') + assert_equal 'Bar', I18n.t(:bar, :default => 'Bah') + assert_equal 'Bah', I18n.t(:bah, :default => 'Bah') # default kicks in only here + end + + test "default" do + assert_equal 'Fuh', I18n.t(:default => 'Fuh') + assert_equal 'Zero', I18n.t(:default => { :zero => 'Zero' }, :count => 0) + assert_equal({ :zero => 'Zero' }, I18n.t(:default => { :zero => 'Zero' })) + assert_equal 'Foo', I18n.t(:default => :foo) + end + + test 'default is returned if translation is missing' do + assert_equal({}, I18n.t(:'i18n.transliterate.rule', :locale => 'en', :default => {})) + end + + test "namespace lookup collects results from all backends" do + assert_equal({ :short => 'short', :long => 'long' }, I18n.t(:formats)) + end + + test "namespace lookup with only the first backend returning a result" do + assert_equal({ :one => '%{count}' }, I18n.t(:plural_1)) + end + + test "pluralization still works" do + assert_equal '1', I18n.t(:plural_1, :count => 1) + assert_equal 'one', I18n.t(:plural_2, :count => 1) + end + + test "bulk lookup collects results from all backends" do + assert_equal ['Foo', 'Bar'], I18n.t([:foo, :bar]) + assert_equal ['Foo', 'Bar', 'Bah'], I18n.t([:foo, :bar, :bah], :default => 'Bah') + assert_equal [{ :short => 'short', :long => 'long' }, { :one => 'one' }, 'Bah'], I18n.t([:formats, :plural_2, :bah], :default => 'Bah') + end + + test "store_translations options are not dropped while transfering to backend" do + @first.expects(:store_translations).with(:foo, {:bar => :baz}, {:option => 'persists'}) + I18n.backend.store_translations :foo, {:bar => :baz}, {:option => 'persists'} + end + + protected + + def backend(translations) + backend = I18n::Backend::Simple.new + translations.each { |locale, data| backend.store_translations(locale, data) } + backend + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/exceptions_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/exceptions_test.rb new file mode 100644 index 0000000..48fbc43 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/exceptions_test.rb @@ -0,0 +1,30 @@ +require 'test_helper' + +class I18nBackendExceptionsTest < Test::Unit::TestCase + def setup + I18n.backend = I18n::Backend::Simple.new + end + + test "throw message: MissingTranslation message from #translate includes the given scope and full key" do + exception = catch(:exception) do + I18n.t(:'baz.missing', :scope => :'foo.bar', :throw => true) + end + assert_equal "translation missing: en.foo.bar.baz.missing", exception.message + end + + test "exceptions: MissingTranslationData message from #translate includes the given scope and full key" do + begin + I18n.t(:'baz.missing', :scope => :'foo.bar', :raise => true) + rescue I18n::MissingTranslationData => exception + end + assert_equal "translation missing: en.foo.bar.baz.missing", exception.message + end + + test "exceptions: MissingTranslationData message from #localize includes the given scope and full key" do + begin + I18n.l(Time.now, :format => :foo) + rescue I18n::MissingTranslationData => exception + end + assert_equal "translation missing: en.time.formats.foo", exception.message + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/fallbacks_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/fallbacks_test.rb new file mode 100644 index 0000000..e743639 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/fallbacks_test.rb @@ -0,0 +1,120 @@ +require 'test_helper' + +class I18nBackendFallbacksTranslateTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Fallbacks + end + + def setup + I18n.backend = Backend.new + store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en') + store_translations(:de, :bar => 'Bar in :de', :baz => 'Baz in :de') + store_translations(:'de-DE', :baz => 'Baz in :de-DE') + end + + test "still returns an existing translation as usual" do + assert_equal 'Foo in :en', I18n.t(:foo, :locale => :en) + assert_equal 'Bar in :de', I18n.t(:bar, :locale => :de) + assert_equal 'Baz in :de-DE', I18n.t(:baz, :locale => :'de-DE') + end + + test "returns the :en translation for a missing :de translation" do + assert_equal 'Foo in :en', I18n.t(:foo, :locale => :de) + end + + test "returns the :de translation for a missing :'de-DE' translation" do + assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE') + end + + test "returns the :en translation for translation missing in both :de and :'de-De'" do + assert_equal 'Buz in :en', I18n.t(:buz, :locale => :'de-DE') + end + + test "returns the :de translation for a missing :'de-DE' when :default is a String" do + assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE', :default => "Default Bar") + assert_equal "Default Bar", I18n.t(:missing_bar, :locale => :'de-DE', :default => "Default Bar") + end + + test "returns the :de translation for a missing :'de-DE' when defaults is a Symbol (which exists in :en)" do + assert_equal "Bar in :de", I18n.t(:bar, :locale => :'de-DE', :default => [:buz]) + end + + test "returns the :'de-DE' default :baz translation for a missing :'de-DE' (which exists in :de)" do + assert_equal "Baz in :de-DE", I18n.t(:bar, :locale => :'de-DE', :default => [:baz]) + end + + test "returns the :de translation for a missing :'de-DE' when :default is a Proc" do + assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE', :default => Proc.new { "Default Bar" }) + assert_equal "Default Bar", I18n.t(:missing_bar, :locale => :'de-DE', :default => Proc.new { "Default Bar" }) + end + + test "returns the :'de-DE' default :baz translation for a missing :'de-DE' when defaults contains Symbol" do + assert_equal 'Baz in :de-DE', I18n.t(:missing_foo, :locale => :'de-DE', :default => [:baz, "Default Bar"]) + end + + test "returns the defaults translation for a missing :'de-DE' when defaults contains a String or Proc before Symbol" do + assert_equal "Default Bar", I18n.t(:missing_foo, :locale => :'de-DE', :default => [:missing_bar, "Default Bar", :baz]) + assert_equal "Default Bar", I18n.t(:missing_foo, :locale => :'de-DE', :default => [:missing_bar, Proc.new { "Default Bar" }, :baz]) + end + + test "returns the default translation for a missing :'de-DE' and existing :de when default is a Hash" do + assert_equal 'Default 6 Bars', I18n.t(:missing_foo, :locale => :'de-DE', :default => [:missing_bar, {:other => "Default %{count} Bars"}, "Default Bar"], :count => 6) + end + + test "raises I18n::MissingTranslationData exception when no translation was found" do + assert_raise(I18n::MissingTranslationData) { I18n.t(:faa, :locale => :en, :raise => true) } + assert_raise(I18n::MissingTranslationData) { I18n.t(:faa, :locale => :de, :raise => true) } + end + + test "should ensure that default is not splitted on new line char" do + assert_equal "Default \n Bar", I18n.t(:missing_bar, :default => "Default \n Bar") + end +end + +class I18nBackendFallbacksLocalizeTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Fallbacks + end + + def setup + I18n.backend = Backend.new + store_translations(:en, :date => { :formats => { :en => 'en' }, :day_names => %w(Sunday) }) + store_translations(:de, :date => { :formats => { :de => 'de' } }) + end + + test "still uses an existing format as usual" do + assert_equal 'en', I18n.l(Date.today, :format => :en, :locale => :en) + end + + test "looks up and uses a fallback locale's format for a key missing in the given locale (1)" do + assert_equal 'en', I18n.l(Date.today, :format => :en, :locale => :de) + end + + test "looks up and uses a fallback locale's format for a key missing in the given locale (2)" do + assert_equal 'de', I18n.l(Date.today, :format => :de, :locale => :'de-DE') + end + + test "still uses an existing day name translation as usual" do + assert_equal 'Sunday', I18n.l(Date.new(2010, 1, 3), :format => '%A', :locale => :en) + end + + test "uses a fallback locale's translation for a key missing in the given locale" do + assert_equal 'Sunday', I18n.l(Date.new(2010, 1, 3), :format => '%A', :locale => :de) + end +end + +class I18nBackendFallbacksWithChainTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Fallbacks + end + + def setup + backend = Backend.new + backend.store_translations(:de, :foo => 'FOO') + I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, backend) + end + + test "falls back from de-DE to de when there is no translation for de-DE available" do + assert_equal 'FOO', I18n.t(:foo, :locale => :'de-DE') + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/interpolation_compiler_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/interpolation_compiler_test.rb new file mode 100644 index 0000000..4af4271 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/interpolation_compiler_test.rb @@ -0,0 +1,102 @@ +require 'test_helper' + +class InterpolationCompilerTest < Test::Unit::TestCase + Compiler = I18n::Backend::InterpolationCompiler::Compiler + + def compile_and_interpolate(str, values = {}) + Compiler.compile_if_an_interpolation(str).i18n_interpolate(values) + end + + def assert_escapes_interpolation_key(expected, malicious_str) + assert_equal(expected, Compiler.send(:escape_key_sym, malicious_str)) + end + + def test_escape_key_properly_escapes + assert_escapes_interpolation_key ':"\""', '"' + assert_escapes_interpolation_key ':"\\\\"', '\\' + assert_escapes_interpolation_key ':"\\\\\""', '\\"' + assert_escapes_interpolation_key ':"\#{}"', '#{}' + assert_escapes_interpolation_key ':"\\\\\#{}"', '\#{}' + end + + def assert_escapes_plain_string(expected, plain_str) + assert_equal expected, Compiler.send(:escape_plain_str, plain_str) + end + + def test_escape_plain_string_properly_escapes + assert_escapes_plain_string '\\"', '"' + assert_escapes_plain_string '\'', '\'' + assert_escapes_plain_string '\\#', '#' + assert_escapes_plain_string '\\#{}', '#{}' + assert_escapes_plain_string '\\\\\\"','\\"' + end + + def test_non_interpolated_strings_or_arrays_dont_get_compiled + ['abc', '\\{a}}', '{a}}', []].each do |obj| + Compiler.compile_if_an_interpolation(obj) + assert_equal false, obj.respond_to?(:i18n_interpolate) + end + end + + def test_interpolated_string_gets_compiled + assert_equal '-A-', compile_and_interpolate('-%{a}-', :a => 'A') + end + + def assert_handles_key(str, key) + assert_equal 'A', compile_and_interpolate(str, key => 'A') + end + + def test_compiles_fancy_keys + assert_handles_key('%{\}', :'\\' ) + assert_handles_key('%{#}', :'#' ) + assert_handles_key('%{#{}', :'#{' ) + assert_handles_key('%{#$SAFE}', :'#$SAFE') + assert_handles_key('%{\000}', :'\000' ) + assert_handles_key('%{\'}', :'\'' ) + assert_handles_key('%{\'\'}', :'\'\'' ) + assert_handles_key('%{a.b}', :'a.b' ) + assert_handles_key('%{ }', :' ' ) + assert_handles_key('%{:}', :':' ) + assert_handles_key("%{:''}", :":''" ) + assert_handles_key('%{:"}', :':"' ) + end + + def test_str_containing_only_escaped_interpolation_is_handled_correctly + assert_equal 'abc %{x}', compile_and_interpolate('abc %%{x}') + end + + def test_handles_weird_strings + assert_equal '#{} a', compile_and_interpolate('#{} %{a}', :a => 'a') + assert_equal '"#{abc}"', compile_and_interpolate('"#{ab%{a}c}"', :a => '' ) + assert_equal 'a}', compile_and_interpolate('%{{a}}', :'{a' => 'a') + assert_equal '"', compile_and_interpolate('"%{a}', :a => '' ) + assert_equal 'a%{a}', compile_and_interpolate('%{a}%%{a}', :a => 'a') + assert_equal '%%{a}', compile_and_interpolate('%%%{a}') + assert_equal '\";eval("a")', compile_and_interpolate('\";eval("%{a}")', :a => 'a') + assert_equal '\";eval("a")', compile_and_interpolate('\";eval("a")%{a}', :a => '' ) + assert_equal "\na", compile_and_interpolate("\n%{a}", :a => 'a') + end +end + +class I18nBackendInterpolationCompilerTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::InterpolationCompiler + end + + include I18n::Tests::Interpolation + + def setup + I18n.backend = Backend.new + super + end + + # pre-compile default strings to make sure we are testing I18n::Backend::InterpolationCompiler + def interpolate(*args) + options = args.last.kind_of?(Hash) ? args.last : {} + if default_str = options[:default] + I18n::Backend::InterpolationCompiler::Compiler.compile_if_an_interpolation(default_str) + end + super + end + +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/key_value_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/key_value_test.rb new file mode 100644 index 0000000..74c6b7d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/key_value_test.rb @@ -0,0 +1,46 @@ +require 'test_helper' + +I18n::Tests.setup_rufus_tokyo + +class I18nBackendKeyValueTest < Test::Unit::TestCase + def setup_backend!(subtree=true) + I18n.backend = I18n::Backend::KeyValue.new(Rufus::Tokyo::Cabinet.new('*'), subtree) + store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' }) + end + + def assert_flattens(expected, nested, escape=true, subtree=true) + assert_equal expected, I18n.backend.flatten_translations("en", nested, escape, subtree) + end + + test "hash flattening works" do + setup_backend! + assert_flattens( + {:a=>'a', :b=>{:c=>'c', :d=>'d', :f=>{:x=>'x'}}, :"b.f" => {:x=>"x"}, :"b.c"=>"c", :"b.f.x"=>"x", :"b.d"=>"d"}, + {:a=>'a', :b=>{:c=>'c', :d=>'d', :f=>{:x=>'x'}}} + ) + assert_flattens({:a=>{:b =>['a', 'b']}, :"a.b"=>['a', 'b']}, {:a=>{:b =>['a', 'b']}}) + assert_flattens({:"a\001b" => "c"}, {:"a.b" => "c"}) + assert_flattens({:"a.b"=>['a', 'b']}, {:a=>{:b =>['a', 'b']}}, true, false) + assert_flattens({:"a.b" => "c"}, {:"a.b" => "c"}, false) + end + + test "store_translations handle subtrees by default" do + setup_backend! + assert_equal({ :bar => 'bar', :baz => 'baz' }, I18n.t("foo")) + end + + test "store_translations merge subtrees accordingly" do + setup_backend! + store_translations(:en, :foo => { :baz => "BAZ"}) + assert_equal('BAZ', I18n.t("foo.baz")) + assert_equal({ :bar => 'bar', :baz => 'BAZ' }, I18n.t("foo")) + end + + test "store_translations does not handle subtrees if desired" do + setup_backend!(false) + assert_raise I18n::MissingTranslationData do + I18n.t("foo", :raise => true) + end + end + +end if defined?(Rufus::Tokyo::Cabinet) diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/memoize_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/memoize_test.rb new file mode 100644 index 0000000..a8a2e11 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/memoize_test.rb @@ -0,0 +1,47 @@ +require 'test_helper' + +require 'backend/simple_test' + +class I18nBackendMemoizeTest < I18nBackendSimpleTest + module MemoizeSpy + attr_accessor :spy_calls + + def available_locales + self.spy_calls = (self.spy_calls || 0) + 1 + super + end + end + + class MemoizeBackend < I18n::Backend::Simple + include MemoizeSpy + include I18n::Backend::Memoize + end + + def setup + super + I18n.backend = MemoizeBackend.new + end + + def test_memoizes_available_locales + I18n.backend.spy_calls = 0 + assert_equal I18n.available_locales, I18n.available_locales + assert_equal 1, I18n.backend.spy_calls + end + + def test_resets_available_locales_on_reload! + I18n.available_locales + I18n.backend.spy_calls = 0 + I18n.reload! + assert_equal I18n.available_locales, I18n.available_locales + assert_equal 1, I18n.backend.spy_calls + end + + def test_resets_available_locales_on_store_translations + I18n.available_locales + I18n.backend.spy_calls = 0 + I18n.backend.store_translations(:copa, :ca => :bana) + assert_equal I18n.available_locales, I18n.available_locales + assert I18n.available_locales.include?(:copa) + assert_equal 1, I18n.backend.spy_calls + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/metadata_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/metadata_test.rb new file mode 100644 index 0000000..96e9f6d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/metadata_test.rb @@ -0,0 +1,67 @@ +require 'test_helper' + +class I18nBackendMetadataTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Metadata + end + + def setup + I18n.backend = Backend.new + store_translations(:en, :foo => 'Hi %{name}') + end + + test "translation strings carry metadata" do + translation = I18n.t(:foo, :name => 'David') + assert translation.respond_to?(:translation_metadata) + assert translation.translation_metadata.is_a?(Hash) + end + + test "translate preserves metadata stored on original Strings" do + store_metadata(:foo, :bar, 'bar') + assert_equal 'bar', I18n.t(:foo, :name => 'David').translation_metadata[:bar] + end + + test "translate preserves metadata stored on original Strings (when interpolated)" do + store_metadata(:foo, :bar, 'bar') + assert_equal 'bar', I18n.t(:foo, :name => 'David').translation_metadata[:bar] + end + + test "translate adds the locale to metadata on Strings" do + assert_equal :en, I18n.t(:foo, :name => 'David', :locale => :en).translation_metadata[:locale] + end + + test "translate adds the key to metadata on Strings" do + assert_equal :foo, I18n.t(:foo, :name => 'David').translation_metadata[:key] + end +# + test "translate adds the default to metadata on Strings" do + assert_equal 'bar', I18n.t(:foo, :default => 'bar', :name => '').translation_metadata[:default] + end + + test "translation adds the interpolation values to metadata on Strings" do + assert_equal({:name => 'David'}, I18n.t(:foo, :name => 'David').translation_metadata[:values]) + end + + test "interpolation adds the original string to metadata on Strings" do + assert_equal('Hi %{name}', I18n.t(:foo, :name => 'David').translation_metadata[:original]) + end + + test "pluralization adds the count to metadata on Strings" do + assert_equal(1, I18n.t(:missing, :count => 1, :default => { :one => 'foo' }).translation_metadata[:count]) + end + + test "metadata works with frozen values" do + assert_equal(1, I18n.t(:missing, :count => 1, :default => 'foo'.freeze).translation_metadata[:count]) + end + + protected + + def translations + I18n.backend.instance_variable_get(:@translations) + end + + def store_metadata(key, name, value) + translations[:en][key].translation_metadata[name] = value + end +end + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/pluralization_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/pluralization_test.rb new file mode 100644 index 0000000..54fbba9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/pluralization_test.rb @@ -0,0 +1,44 @@ +require 'test_helper' + +class I18nBackendPluralizationTest < Test::Unit::TestCase + class Backend < I18n::Backend::Simple + include I18n::Backend::Pluralization + include I18n::Backend::Fallbacks + end + + def setup + I18n.backend = Backend.new + @rule = lambda { |n| n == 1 ? :one : n == 0 || (2..10).include?(n % 100) ? :few : (11..19).include?(n % 100) ? :many : :other } + store_translations(:xx, :i18n => { :plural => { :rule => @rule } }) + @entry = { :zero => 'zero', :one => 'one', :few => 'few', :many => 'many', :other => 'other' } + end + + test "pluralization picks a pluralizer from :'i18n.pluralize'" do + assert_equal @rule, I18n.backend.send(:pluralizer, :xx) + end + + test "pluralization picks :one for 1" do + assert_equal 'one', I18n.t(:count => 1, :default => @entry, :locale => :xx) + end + + test "pluralization picks :few for 2" do + assert_equal 'few', I18n.t(:count => 2, :default => @entry, :locale => :xx) + end + + test "pluralization picks :many for 11" do + assert_equal 'many', I18n.t(:count => 11, :default => @entry, :locale => :xx) + end + + test "pluralization picks zero for 0 if the key is contained in the data" do + assert_equal 'zero', I18n.t(:count => 0, :default => @entry, :locale => :xx) + end + + test "pluralization picks few for 0 if the key is not contained in the data" do + @entry.delete(:zero) + assert_equal 'few', I18n.t(:count => 0, :default => @entry, :locale => :xx) + end + + test "Fallbacks can pick up rules from fallback locales, too" do + assert_equal @rule, I18n.backend.send(:pluralizer, :'xx-XX') + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/simple_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/simple_test.rb new file mode 100644 index 0000000..3ebc8ee --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/simple_test.rb @@ -0,0 +1,83 @@ +require 'test_helper' + +class I18nBackendSimpleTest < Test::Unit::TestCase + def setup + I18n.backend = I18n::Backend::Simple.new + I18n.load_path = [locales_dir + '/en.yml'] + end + + # useful because this way we can use the backend with no key for interpolation/pluralization + test "simple backend translate: given nil as a key it still interpolations the default value" do + assert_equal "Hi David", I18n.t(nil, :default => "Hi %{name}", :name => "David") + end + + # loading translations + test "simple load_translations: given an unknown file type it raises I18n::UnknownFileType" do + assert_raise(I18n::UnknownFileType) { I18n.backend.load_translations("#{locales_dir}/en.xml") } + end + + test "simple load_translations: given a Ruby file name it does not raise anything" do + assert_nothing_raised { I18n.backend.load_translations("#{locales_dir}/en.rb") } + end + + test "simple load_translations: given no argument, it uses I18n.load_path" do + I18n.backend.load_translations + assert_equal({ :en => { :foo => { :bar => 'baz' } } }, I18n.backend.send(:translations)) + end + + test "simple load_rb: loads data from a Ruby file" do + data = I18n.backend.send(:load_rb, "#{locales_dir}/en.rb") + assert_equal({ :en => { :fuh => { :bah => 'bas' } } }, data) + end + + test "simple load_yml: loads data from a YAML file" do + data = I18n.backend.send(:load_yml, "#{locales_dir}/en.yml") + assert_equal({ 'en' => { 'foo' => { 'bar' => 'baz' } } }, data) + end + + test "simple load_translations: loads data from known file formats" do + I18n.backend = I18n::Backend::Simple.new + I18n.backend.load_translations("#{locales_dir}/en.rb", "#{locales_dir}/en.yml") + expected = { :en => { :fuh => { :bah => "bas" }, :foo => { :bar => "baz" } } } + assert_equal expected, translations + end + + test "simple load_translations: given file names as array it does not raise anything" do + assert_nothing_raised { I18n.backend.load_translations(["#{locales_dir}/en.rb", "#{locales_dir}/en.yml"]) } + end + + # storing translations + + test "simple store_translations: stores translations, ... no, really :-)" do + I18n.backend.store_translations :'en', :foo => 'bar' + assert_equal Hash[:'en', {:foo => 'bar'}], translations + end + + test "simple store_translations: deep_merges with existing translations" do + I18n.backend.store_translations :'en', :foo => {:bar => 'bar'} + I18n.backend.store_translations :'en', :foo => {:baz => 'baz'} + assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], translations + end + + test "simple store_translations: converts the given locale to a Symbol" do + I18n.backend.store_translations 'en', :foo => 'bar' + assert_equal Hash[:'en', {:foo => 'bar'}], translations + end + + test "simple store_translations: converts keys to Symbols" do + I18n.backend.store_translations 'en', 'foo' => {'bar' => 'bar', 'baz' => 'baz'} + assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], translations + end + + # reloading translations + + test "simple reload_translations: unloads translations" do + I18n.backend.reload! + assert_nil translations + end + + test "simple reload_translations: uninitializes the backend" do + I18n.backend.reload! + assert_equal I18n.backend.initialized?, false + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/transliterator_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/transliterator_test.rb new file mode 100644 index 0000000..c2e1e40 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/backend/transliterator_test.rb @@ -0,0 +1,81 @@ +# :coding: utf-8 +require 'test_helper' + +class I18nBackendTransliterator < Test::Unit::TestCase + def setup + I18n.backend = I18n::Backend::Simple.new + @proc = lambda { |n| n.upcase } + @hash = { :"ü" => "ue", :"ö" => "oe" } + @transliterator = I18n::Backend::Transliterator.get + end + + test "transliteration rule can be a proc" do + store_translations(:xx, :i18n => {:transliterate => {:rule => @proc}}) + assert_equal "HELLO", I18n.backend.transliterate(:xx, "hello") + end + + test "transliteration rule can be a hash" do + store_translations(:xx, :i18n => {:transliterate => {:rule => @hash}}) + assert_equal "ue", I18n.backend.transliterate(:xx, "ü") + end + + test "transliteration rule must be a proc or hash" do + store_translations(:xx, :i18n => {:transliterate => {:rule => ""}}) + assert_raise I18n::ArgumentError do + I18n.backend.transliterate(:xx, "ü") + end + end + + test "transliterator defaults to latin => ascii when no rule is given" do + assert_equal "AEroskobing", I18n.backend.transliterate(:xx, "Ærøskøbing") + end + + test "default transliterator should not modify ascii characters" do + (0..127).each do |byte| + char = [byte].pack("U") + assert_equal char, @transliterator.transliterate(char) + end + end + + test "default transliterator correctly transliterates latin characters" do + # create string with range of Unicode's western characters with + # diacritics, excluding the division and multiplication signs which for + # some reason or other are floating in the middle of all the letters. + string = (0xC0..0x17E).to_a.reject {|c| [0xD7, 0xF7].include? c}.pack("U*") + string.split(//) do |char| + assert_match %r{^[a-zA-Z']*$}, @transliterator.transliterate(string) + end + end + + test "should replace non-ASCII chars not in map with a replacement char" do + assert_equal "abc?", @transliterator.transliterate("abcÅ¿") + end + + test "can replace non-ASCII chars not in map with a custom replacement string" do + assert_equal "abc#", @transliterator.transliterate("abcÅ¿", "#") + end + + if RUBY_VERSION >= "1.9" + test "default transliterator raises errors for invalid UTF-8" do + assert_raise ArgumentError do + @transliterator.transliterate("a\x92b") + end + end + end + + test "I18n.transliterate should transliterate using a default transliterator" do + assert_equal "aeo", I18n.transliterate("áèö") + end + + test "I18n.transliterate should transliterate using a locale" do + store_translations(:xx, :i18n => {:transliterate => {:rule => @hash}}) + assert_equal "ue", I18n.transliterate("ü", :locale => :xx) + end + + test "default transliterator fails with custom rules with uncomposed input" do + char = [117, 776].pack("U*") # "ü" as ASCII "u" plus COMBINING DIAERESIS + transliterator = I18n::Backend::Transliterator.get(@hash) + assert_not_equal "ue", transliterator.transliterate(char) + end + +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/core_ext/hash_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/core_ext/hash_test.rb new file mode 100644 index 0000000..25c5748 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/core_ext/hash_test.rb @@ -0,0 +1,30 @@ +require 'test_helper' +require 'i18n/core_ext/hash' + +class I18nCoreExtHashInterpolationTest < Test::Unit::TestCase + test "#deep_symbolize_keys" do + hash = { 'foo' => { 'bar' => { 'baz' => 'bar' } } } + expected = { :foo => { :bar => { :baz => 'bar' } } } + assert_equal expected, hash.deep_symbolize_keys + end + + test "#slice" do + hash = { :foo => 'bar', :baz => 'bar' } + expected = { :foo => 'bar' } + assert_equal expected, hash.slice(:foo) + end + + test "#except" do + hash = { :foo => 'bar', :baz => 'bar' } + expected = { :foo => 'bar' } + assert_equal expected, hash.except(:baz) + end + + test "#deep_merge!" do + hash = { :foo => { :bar => { :baz => 'bar' } }, :baz => 'bar' } + hash.deep_merge!(:foo => { :bar => { :baz => 'foo' } }) + + expected = { :foo => { :bar => { :baz => 'foo' } }, :baz => 'bar' } + assert_equal expected, hash + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/core_ext/string/interpolate_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/core_ext/string/interpolate_test.rb new file mode 100644 index 0000000..993d454 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/core_ext/string/interpolate_test.rb @@ -0,0 +1,99 @@ +require 'test_helper' + +# thanks to Masao's String extensions these should work the same in +# Ruby 1.8 (patched) and Ruby 1.9 (native) +# some tests taken from Masao's tests +# http://github.com/mutoh/gettext/blob/edbbe1fa8238fa12c7f26f2418403015f0270e47/test/test_string.rb + +class I18nCoreExtStringInterpolationTest < Test::Unit::TestCase + test "String interpolates a single argument" do + assert_equal "Masao", "%s" % "Masao" + end + + test "String interpolates an array argument" do + assert_equal "1 message", "%d %s" % [1, 'message'] + end + + test "String interpolates a hash argument w/ named placeholders" do + assert_equal "Masao Mutoh", "%{first} %{last}" % { :first => 'Masao', :last => 'Mutoh' } + end + + test "String interpolates a hash argument w/ named placeholders (reverse order)" do + assert_equal "Mutoh, Masao", "%{last}, %{first}" % { :first => 'Masao', :last => 'Mutoh' } + end + + test "String interpolates named placeholders with sprintf syntax" do + assert_equal "10, 43.4", "%d, %.1f" % {:integer => 10, :float => 43.4} + end + + test "String interpolates named placeholders with sprintf syntax, does not recurse" do + assert_equal "%s", "%{msg}" % { :msg => '%s', :not_translated => 'should not happen' } + end + + test "String interpolation does not replace anything when no placeholders are given" do + assert_equal("aaa", "aaa" % {:num => 1}) + assert_equal("bbb", "bbb" % [1]) + end + + test "String interpolation sprintf behaviour equals Ruby 1.9 behaviour" do + assert_equal("1", "%d" % {:num => 1}) + assert_equal("0b1", "%#b" % {:num => 1}) + assert_equal("foo", "%s" % {:msg => "foo"}) + assert_equal("1.000000", "%f" % {:num => 1.0}) + assert_equal(" 1", "%3.0f" % {:num => 1.0}) + assert_equal("100.00", "%2.2f" % {:num => 100.0}) + assert_equal("0x64", "%#x" % {:num => 100.0}) + assert_raise(ArgumentError) { "%,d" % {:num => 100} } + assert_raise(ArgumentError) { "%/d" % {:num => 100} } + end + + test "String interpolation old-style sprintf still works" do + assert_equal("foo 1.000000", "%s %f" % ["foo", 1.0]) + end + + test "String interpolation raises an ArgumentError when the string has extra placeholders (Array)" do + assert_raise(ArgumentError) do # Ruby 1.9 msg: "too few arguments" + "%s %s" % %w(Masao) + end + end + + test "String interpolation raises a KeyError when the string has extra placeholders (Hash)" do + assert_raise(KeyError) do # Ruby 1.9 msg: "key not found" + "%{first} %{last}" % { :first => 'Masao' } + end + end + + test "String interpolation does not raise when passed extra values (Array)" do + assert_nothing_raised do + assert_equal "Masao", "%s" % %w(Masao Mutoh) + end + end + + test "String interpolation does not raise when passed extra values (Hash)" do + assert_nothing_raised do + assert_equal "Masao Mutoh", "%{first} %{last}" % { :first => 'Masao', :last => 'Mutoh', :salutation => 'Mr.' } + end + end + + test "% acts as escape character in String interpolation" do + assert_equal "%{first}", "%%{first}" % { :first => 'Masao' } + assert_equal("% 1", "%% %d" % {:num => 1.0}) + assert_equal("%{num} %d", "%%{num} %%d" % {:num => 1}) + end + + test "% can be used in Ruby's own sprintf behavior" do + assert_equal "70%", "%d%%" % 70 + assert_equal "70-100%", "%d-%d%%" % [70, 100] + assert_equal "+2.30%", "%+.2f%%" % 2.3 + end + + def test_sprintf_mix_unformatted_and_formatted_named_placeholders + assert_equal("foo 1.000000", "%{name} %f" % {:name => "foo", :num => 1.0}) + end + + def test_string_interpolation_raises_an_argument_error_when_mixing_named_and_unnamed_placeholders + assert_raise(ArgumentError) { "%{name} %f" % [1.0] } + assert_raise(ArgumentError) { "%{name} %f" % [1.0, 2.0] } + end +end + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/gettext/api_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/gettext/api_test.rb new file mode 100644 index 0000000..947b5a2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/gettext/api_test.rb @@ -0,0 +1,206 @@ +# encoding: utf-8 +require 'test_helper' +require 'i18n/gettext/helpers' + +include I18n::Gettext::Helpers + +class I18nGettextApiTest < Test::Unit::TestCase + def setup + I18n.locale = :en + I18n.backend.store_translations :de, { + 'Hi Gettext!' => 'Hallo Gettext!', + 'Sentence 1. Sentence 2.' => 'Satz 1. Satz 2.', + "An apple" => { :one => 'Ein Apfel', :other => '%{count} Äpfel' }, + :special => { "A special apple" => { :one => 'Ein spezieller Apfel', :other => '%{count} spezielle Äpfel' } }, + :foo => { :bar => 'bar-de' }, + 'foo.bar' => 'Foo Bar' + }, :separator => '|' + end + + # gettext + def test_gettext_uses_msg_as_default + assert_equal 'Hi Gettext!', _('Hi Gettext!') + end + + def test_gettext_uses_msg_as_key + I18n.locale = :de + assert_equal 'Hallo Gettext!', gettext('Hi Gettext!') + assert_equal 'Hallo Gettext!', _('Hi Gettext!') + end + + def test_gettext_uses_msg_containing_dots_as_default + assert_equal 'Sentence 1. Sentence 2.', gettext('Sentence 1. Sentence 2.') + assert_equal 'Sentence 1. Sentence 2.', _('Sentence 1. Sentence 2.') + end + + def test_gettext_uses_msg_containing_dots_as_key + I18n.locale = :de + assert_equal 'Satz 1. Satz 2.', gettext('Sentence 1. Sentence 2.') + assert_equal 'Satz 1. Satz 2.', _('Sentence 1. Sentence 2.') + end + + # sgettext + def test_sgettext_defaults_to_the_last_token_of_a_scoped_msgid + assert_equal 'bar', sgettext('foo|bar') + assert_equal 'bar', s_('foo|bar') + end + + def test_sgettext_looks_up_a_scoped_translation + I18n.locale = :de + assert_equal 'bar-de', sgettext('foo|bar') + assert_equal 'bar-de', s_('foo|bar') + end + + def test_sgettext_ignores_dots + I18n.locale = :de + assert_equal 'Foo Bar', sgettext('foo.bar') + assert_equal 'Foo Bar', s_('foo.bar') + end + + # pgettext + def test_pgettext_defaults_to_msgid + assert_equal 'bar', pgettext('foo', 'bar') + assert_equal 'bar', p_('foo', 'bar') + end + + def test_pgettext_looks_up_a_scoped_translation + I18n.locale = :de + assert_equal 'bar-de', pgettext('foo', 'bar') + assert_equal 'bar-de', p_('foo', 'bar') + end + + # ngettext + def test_ngettext_looks_up_msg_id_as_default_singular + assert_equal 'An apple', ngettext('An apple', '%{count} apples', 1) + assert_equal 'An apple', n_('An apple', '%{count} apples', 1) + end + + def test_ngettext_looks_up_msg_id_plural_as_default_plural + assert_equal '2 apples', ngettext('An apple', '%{count} apples', 2) + assert_equal '2 apples', n_('An apple', '%{count} apples', 2) + end + + def test_ngettext_looks_up_a_singular + I18n.locale = :de + assert_equal 'Ein Apfel', ngettext('An apple', '%{count} apples', 1) + assert_equal 'Ein Apfel', n_('An apple', '%{count} apples', 1) + end + + def test_ngettext_looks_up_a_plural + I18n.locale = :de + assert_equal '2 Äpfel', ngettext('An apple', '%{count} apples', 2) + assert_equal '2 Äpfel', n_('An apple', '%{count} apples', 2) + end + + def test_ngettext_looks_up_msg_id_as_default_singular_with_alternative_syntax + assert_equal 'An apple', ngettext(['An apple', '%{count} apples'], 1) + assert_equal 'An apple', n_(['An apple', '%{count} apples'], 1) + end + + def test_ngettext_looks_up_msg_id_plural_as_default_plural_with_alternative_syntax + assert_equal '2 apples', ngettext(['An apple', '%{count} apples'], 2) + assert_equal '2 apples', n_(['An apple', '%{count} apples'], 2) + end + + def test_ngettext_looks_up_a_singular_with_alternative_syntax + I18n.locale = :de + assert_equal 'Ein Apfel', ngettext(['An apple', '%{count} apples'], 1) + assert_equal 'Ein Apfel', n_(['An apple', '%{count} apples'], 1) + end + + def test_ngettext_looks_up_a_plural_with_alternative_syntax + I18n.locale = :de + assert_equal '2 Äpfel', ngettext(['An apple', '%{count} apples'], 2) + assert_equal '2 Äpfel', n_(['An apple', '%{count} apples'], 2) + end + + # nsgettext + def test_nsgettext_looks_up_msg_id_as_default_singular + assert_equal 'A special apple', nsgettext('special|A special apple', '%{count} special apples', 1) + assert_equal 'A special apple', ns_('special|A special apple', '%{count} special apples', 1) + end + + def test_nsgettext_looks_up_msg_id_plural_as_default_plural + assert_equal '2 special apples', nsgettext('special|A special apple', '%{count} special apples', 2) + assert_equal '2 special apples', ns_('special|A special apple', '%{count} special apples', 2) + end + + def test_nsgettext_looks_up_a_singular + I18n.locale = :de + assert_equal 'Ein spezieller Apfel', nsgettext('special|A special apple', '%{count} special apples', 1) + assert_equal 'Ein spezieller Apfel', ns_('special|A special apple', '%{count} special apples', 1) + end + + def test_nsgettext_looks_up_a_plural + I18n.locale = :de + assert_equal '2 spezielle Äpfel', nsgettext('special|A special apple', '%{count} special apples', 2) + assert_equal '2 spezielle Äpfel', ns_('special|A special apple', '%{count} special apples', 2) + end + + def test_nsgettext_looks_up_msg_id_as_default_singular_with_alternative_syntax + assert_equal 'A special apple', nsgettext(['special|A special apple', '%{count} special apples'], 1) + assert_equal 'A special apple', ns_(['special|A special apple', '%{count} special apples'], 1) + end + + def test_nsgettext_looks_up_msg_id_plural_as_default_plural_with_alternative_syntax + assert_equal '2 special apples', nsgettext(['special|A special apple', '%{count} special apples'], 2) + assert_equal '2 special apples', ns_(['special|A special apple', '%{count} special apples'], 2) + end + + def test_nsgettext_looks_up_a_singular_with_alternative_syntax + I18n.locale = :de + assert_equal 'Ein spezieller Apfel', nsgettext(['special|A special apple', '%{count} special apples'], 1) + assert_equal 'Ein spezieller Apfel', ns_(['special|A special apple', '%{count} special apples'], 1) + end + + def test_nsgettext_looks_up_a_plural_with_alternative_syntax + I18n.locale = :de + assert_equal '2 spezielle Äpfel', nsgettext(['special|A special apple', '%{count} special apples'], 2) + assert_equal '2 spezielle Äpfel', ns_(['special|A special apple', '%{count} special apples'], 2) + end + + # npgettext + def test_npgettext_looks_up_msg_id_as_default_singular + assert_equal 'A special apple', npgettext('special', 'A special apple', '%{count} special apples', 1) + assert_equal 'A special apple', np_('special', 'A special apple', '%{count} special apples', 1) + end + + def test_npgettext_looks_up_msg_id_plural_as_default_plural + assert_equal '2 special apples', npgettext('special', 'A special apple', '%{count} special apples', 2) + assert_equal '2 special apples', np_('special', 'A special apple', '%{count} special apples', 2) + end + + def test_npgettext_looks_up_a_singular + I18n.locale = :de + assert_equal 'Ein spezieller Apfel', npgettext('special', 'A special apple', '%{count} special apples', 1) + assert_equal 'Ein spezieller Apfel', np_('special', 'A special apple', '%{count} special apples', 1) + end + + def test_npgettext_looks_up_a_plural + I18n.locale = :de + assert_equal '2 spezielle Äpfel', npgettext('special', 'A special apple', '%{count} special apples', 2) + assert_equal '2 spezielle Äpfel', np_('special', 'A special apple', '%{count} special apples', 2) + end + + def test_npgettext_looks_up_msg_id_as_default_singular_with_alternative_syntax + assert_equal 'A special apple', npgettext('special', ['A special apple', '%{count} special apples'], 1) + assert_equal 'A special apple', np_('special', ['A special apple', '%{count} special apples'], 1) + end + + def test_npgettext_looks_up_msg_id_plural_as_default_plural_with_alternative_syntax + assert_equal '2 special apples', npgettext('special', ['A special apple', '%{count} special apples'], 2) + assert_equal '2 special apples', np_('special', ['A special apple', '%{count} special apples'], 2) + end + + def test_npgettext_looks_up_a_singular_with_alternative_syntax + I18n.locale = :de + assert_equal 'Ein spezieller Apfel', npgettext('special', ['A special apple', '%{count} special apples'], 1) + assert_equal 'Ein spezieller Apfel', np_('special', ['A special apple', '%{count} special apples'], 1) + end + + def test_npgettext_looks_up_a_plural_with_alternative_syntax + I18n.locale = :de + assert_equal '2 spezielle Äpfel', npgettext('special', ['A special apple', '%{count} special apples'], 2) + assert_equal '2 spezielle Äpfel', np_('special', ['A special apple', '%{count} special apples'], 2) + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/gettext/backend_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/gettext/backend_test.rb new file mode 100644 index 0000000..ecb6e0c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/gettext/backend_test.rb @@ -0,0 +1,93 @@ +# encoding: utf-8 + +require 'test_helper' + +# apparently Ruby 1.9.1p129 has encoding problems with the gettext po parser +unless RUBY_VERSION == '1.9.1' && RUBY_PATCHLEVEL <= 129 + + class I18nGettextBackendTest < Test::Unit::TestCase + include I18n::Gettext::Helpers + + class Backend < I18n::Backend::Simple + include I18n::Backend::Gettext + end + + def setup + I18n.backend = Backend.new + I18n.locale = :en + I18n.load_path = ["#{locales_dir}/de.po"] + @old_separator, I18n.default_separator = I18n.default_separator, '|' + end + + def teardown + I18n.load_path = nil + I18n.backend = nil + I18n.default_separator = @old_separator + end + + def test_backend_loads_po_file + I18n.backend.send(:init_translations) + assert I18n.backend.send(:translations)[:de][:"Axis"] + end + + def test_looks_up_a_translation + I18n.locale = :de + assert_equal 'Auto', gettext('car') + end + + def test_uses_default_translation + assert_equal 'car', gettext('car') + end + + def test_looks_up_a_namespaced_translation + I18n.locale = :de + assert_equal 'Räderzahl', sgettext('Car|Wheels count') + assert_equal 'Räderzahl', pgettext('Car', 'Wheels count') + end + + def test_uses_namespaced_default_translation + assert_equal 'Wheels count', sgettext('Car|Wheels count') + assert_equal 'Wheels count', pgettext('Car', 'Wheels count') + end + + def test_pluralizes_entry + I18n.locale = :de + assert_equal 'Achse', ngettext('Axis', 'Axis', 1) + assert_equal 'Achsen', ngettext('Axis', 'Axis', 2) + end + + def test_pluralizes_default_entry + assert_equal 'Axis', ngettext('Axis', 'Axis', 1) + assert_equal 'Axis', ngettext('Axis', 'Axis', 2) + end + + def test_pluralizes_namespaced_entry + I18n.locale = :de + assert_equal 'Rad', nsgettext('Car|wheel', 'wheels', 1) + assert_equal 'Räder', nsgettext('Car|wheel', 'wheels', 2) + assert_equal 'Rad', npgettext('Car', 'wheel', 'wheels', 1) + assert_equal 'Räder', npgettext('Car', 'wheel', 'wheels', 2) + end + + def test_pluralizes_namespaced_default_entry + assert_equal 'wheel', nsgettext('Car|wheel', 'wheels', 1) + assert_equal 'wheels', nsgettext('Car|wheel', 'wheels', 2) + assert_equal 'wheel', npgettext('Car', 'wheel', 'wheels', 1) + assert_equal 'wheels', npgettext('Car', 'wheel', 'wheels', 2) + end + + def test_pluralizes_namespaced_entry_with_alternative_syntax + I18n.locale = :de + assert_equal 'Rad', nsgettext(['Car|wheel', 'wheels'], 1) + assert_equal 'Räder', nsgettext(['Car|wheel', 'wheels'], 2) + assert_equal 'Rad', npgettext('Car', ['wheel', 'wheels'], 1) + assert_equal 'Räder', npgettext('Car', ['wheel', 'wheels'], 2) + end + + def test_ngettextpluralizes_entry_with_dots + I18n.locale = :de + assert_equal 'Auf 1 Achse.', n_("On %{count} wheel.", "On %{count} wheels.", 1) + assert_equal 'Auf 2 Achsen.', n_("On %{count} wheel.", "On %{count} wheels.", 2) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/exceptions_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/exceptions_test.rb new file mode 100644 index 0000000..fcc50f3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/exceptions_test.rb @@ -0,0 +1,116 @@ +require 'test_helper' + +class I18nExceptionsTest < Test::Unit::TestCase + def test_invalid_locale_stores_locale + force_invalid_locale + rescue I18n::ArgumentError => e + assert_nil exception.locale + end + + test "passing an invalid locale raises an InvalidLocale exception" do + force_invalid_locale do |exception| + assert_equal 'nil is not a valid locale', exception.message + end + end + + test "MissingTranslationData exception stores locale, key and options" do + force_missing_translation_data do |exception| + assert_equal 'de', exception.locale + assert_equal :foo, exception.key + assert_equal({:scope => :bar}, exception.options) + end + end + + test "MissingTranslationData message contains the locale and scoped key" do + force_missing_translation_data do |exception| + assert_equal 'translation missing: de.bar.foo', exception.message + end + end + + test "MissingTranslationData html_message is a span with the titlelized last key token" do + force_missing_translation_data do |exception| + assert_equal 'Foo', exception.html_message + end + end + + test "ExceptionHandler returns the html_message if :rescue_format => :html was given" do + message = force_missing_translation_data(:rescue_format => :html) + assert_equal 'Foo', message + end + + test "InvalidPluralizationData stores entry and count" do + force_invalid_pluralization_data do |exception| + assert_equal [:bar], exception.entry + assert_equal 1, exception.count + end + end + + test "InvalidPluralizationData message contains count and data" do + force_invalid_pluralization_data do |exception| + assert_equal 'translation data [:bar] can not be used with :count => 1', exception.message + end + end + + test "MissingInterpolationArgument stores key and string" do + assert_raise(I18n::MissingInterpolationArgument) { force_missing_interpolation_argument } + force_missing_interpolation_argument do |exception| + # assert_equal :bar, exception.key + assert_equal "%{bar}", exception.string + end + end + + test "MissingInterpolationArgument message contains the missing and given arguments" do + force_missing_interpolation_argument do |exception| + assert_equal 'missing interpolation argument in "%{bar}" ({:baz=>"baz"} given)', exception.message + end + end + + test "ReservedInterpolationKey stores key and string" do + force_reserved_interpolation_key do |exception| + assert_equal :scope, exception.key + assert_equal "%{scope}", exception.string + end + end + + test "ReservedInterpolationKey message contains the reserved key" do + force_reserved_interpolation_key do |exception| + assert_equal 'reserved key :scope used in "%{scope}"', exception.message + end + end + + private + + def force_invalid_locale + I18n.translate(:foo, :locale => nil) + rescue I18n::ArgumentError => e + block_given? ? yield(e) : raise(e) + end + + def force_missing_translation_data(options = {}) + I18n.backend.store_translations('de', :bar => nil) + I18n.translate(:foo, options.merge(:scope => :bar, :locale => :de)) + rescue I18n::ArgumentError => e + block_given? ? yield(e) : raise(e) + end + + def force_invalid_pluralization_data + I18n.backend.store_translations('de', :foo => [:bar]) + I18n.translate(:foo, :count => 1, :locale => :de) + rescue I18n::ArgumentError => e + block_given? ? yield(e) : raise(e) + end + + def force_missing_interpolation_argument + I18n.backend.store_translations('de', :foo => "%{bar}") + I18n.translate(:foo, :baz => 'baz', :locale => :de) + rescue I18n::ArgumentError => e + block_given? ? yield(e) : raise(e) + end + + def force_reserved_interpolation_key + I18n.backend.store_translations('de', :foo => "%{scope}") + I18n.translate(:foo, :baz => 'baz', :locale => :de) + rescue I18n::ArgumentError => e + block_given? ? yield(e) : raise(e) + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/interpolate_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/interpolate_test.rb new file mode 100644 index 0000000..ee8849b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/interpolate_test.rb @@ -0,0 +1,61 @@ +require 'test_helper' +require 'i18n/core_ext/string/interpolate' + +# thanks to Masao's String extensions, some tests taken from Masao's tests +# http://github.com/mutoh/gettext/blob/edbbe1fa8238fa12c7f26f2418403015f0270e47/test/test_string.rb + +class I18nInterpolateTest < Test::Unit::TestCase + test "String interpolates a hash argument w/ named placeholders" do + assert_equal "Masao Mutoh", I18n.interpolate("%{first} %{last}", :first => 'Masao', :last => 'Mutoh' ) + end + + test "String interpolates a hash argument w/ named placeholders (reverse order)" do + assert_equal "Mutoh, Masao", I18n.interpolate("%{last}, %{first}", :first => 'Masao', :last => 'Mutoh' ) + end + + test "String interpolates named placeholders with sprintf syntax" do + assert_equal "10, 43.4", I18n.interpolate("%d, %.1f", :integer => 10, :float => 43.4) + end + + test "String interpolates named placeholders with sprintf syntax, does not recurse" do + assert_equal "%s", I18n.interpolate("%{msg}", :msg => '%s', :not_translated => 'should not happen' ) + end + + test "String interpolation does not replace anything when no placeholders are given" do + assert_equal "aaa", I18n.interpolate("aaa", :num => 1) + end + + test "String interpolation sprintf behaviour equals Ruby 1.9 behaviour" do + assert_equal "1", I18n.interpolate("%d", :num => 1) + assert_equal "0b1", I18n.interpolate("%#b", :num => 1) + assert_equal "foo", I18n.interpolate("%s", :msg => "foo") + assert_equal "1.000000", I18n.interpolate("%f", :num => 1.0) + assert_equal " 1", I18n.interpolate("%3.0f", :num => 1.0) + assert_equal "100.00", I18n.interpolate("%2.2f", :num => 100.0) + assert_equal "0x64", I18n.interpolate("%#x", :num => 100.0) + assert_raise(ArgumentError) { I18n.interpolate("%,d", :num => 100) } + assert_raise(ArgumentError) { I18n.interpolate("%/d", :num => 100) } + end + + test "String interpolation raises an I18n::MissingInterpolationArgument when the string has extra placeholders" do + assert_raise(I18n::MissingInterpolationArgument) do # Ruby 1.9 msg: "key not found" + I18n.interpolate("%{first} %{last}", :first => 'Masao') + end + end + + test "String interpolation does not raise when extra values were passed" do + assert_nothing_raised do + assert_equal "Masao Mutoh", I18n.interpolate("%{first} %{last}", :first => 'Masao', :last => 'Mutoh', :salutation => 'Mr.' ) + end + end + + test "% acts as escape character in String interpolation" do + assert_equal "%{first}", I18n.interpolate("%%{first}", :first => 'Masao') + assert_equal "% 1", I18n.interpolate("%% %d", :num => 1.0) + assert_equal "%{num} %d", I18n.interpolate("%%{num} %%d", :num => 1) + end + + def test_sprintf_mix_unformatted_and_formatted_named_placeholders + assert_equal "foo 1.000000", I18n.interpolate("%{name} %f", :name => "foo", :num => 1.0) + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/load_path_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/load_path_test.rb new file mode 100644 index 0000000..678c893 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n/load_path_test.rb @@ -0,0 +1,26 @@ +require 'test_helper' + +class I18nLoadPathTest < Test::Unit::TestCase + def setup + I18n.locale = :en + I18n.backend = I18n::Backend::Simple.new + store_translations(:en, :foo => {:bar => 'bar', :baz => 'baz'}) + end + + test "nested load paths do not break locale loading" do + I18n.load_path = [[locales_dir + '/en.yml']] + assert_equal "baz", I18n.t(:'foo.bar') + end + + test "loading an empty yml file raises an InvalidLocaleData exception" do + assert_raise I18n::InvalidLocaleData do + I18n.load_path = [[locales_dir + '/invalid/empty.yml']] + I18n.t(:'foo.bar', :default => "baz") + end + end + + test "adding arrays of filenames to the load path does not break locale loading" do + I18n.load_path << Dir[locales_dir + '/*.{rb,yml}'] + assert_equal "baz", I18n.t(:'foo.bar') + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n_test.rb new file mode 100644 index 0000000..ad7872e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/i18n_test.rb @@ -0,0 +1,236 @@ +require 'test_helper' + +class I18nTest < Test::Unit::TestCase + def setup + I18n.backend.store_translations(:'en', :currency => { :format => { :separator => '.', :delimiter => ',', } }) + end + + test "exposes its VERSION constant" do + assert I18n::VERSION + end + + test "uses the simple backend by default" do + assert I18n.backend.is_a?(I18n::Backend::Simple) + end + + test "can set the backend" do + begin + assert_nothing_raised { I18n.backend = self } + assert_equal self, I18n.backend + ensure + I18n.backend = I18n::Backend::Simple.new + end + end + + test "uses :en as a default_locale by default" do + assert_equal :en, I18n.default_locale + end + + test "can set the default locale" do + begin + assert_nothing_raised { I18n.default_locale = 'de' } + assert_equal :de, I18n.default_locale + ensure + I18n.default_locale = :en + end + end + + test "uses the default locale as a locale by default" do + assert_equal I18n.default_locale, I18n.locale + end + + test "sets the current locale to Thread.current" do + assert_nothing_raised { I18n.locale = 'de' } + assert_equal :de, I18n.locale + assert_equal :de, Thread.current[:i18n_config].locale + I18n.locale = :en + end + + test "can set the configuration object" do + begin + I18n.config = self + assert_equal self, I18n.config + assert_equal self, Thread.current[:i18n_config] + ensure + I18n.config = ::I18n::Config.new + end + end + + test "locale is not shared between configurations" do + a = I18n::Config.new + b = I18n::Config.new + a.locale = :fr + b.locale = :es + assert_equal :fr, a.locale + assert_equal :es, b.locale + assert_equal :en, I18n.locale + end + + test "other options are shared between configurations" do + begin + a = I18n::Config.new + b = I18n::Config.new + a.default_locale = :fr + b.default_locale = :es + assert_equal :es, a.default_locale + assert_equal :es, b.default_locale + assert_equal :es, I18n.default_locale + ensure + I18n.default_locale = :en + end + end + + test "uses a dot as a default_separator by default" do + assert_equal '.', I18n.default_separator + end + + test "can set the default_separator" do + begin + assert_nothing_raised { I18n.default_separator = "\001" } + ensure + I18n.default_separator = '.' + end + end + + test "normalize_keys normalizes given locale, keys and scope to an array of single-key symbols" do + assert_equal [:en, :foo, :bar], I18n.normalize_keys(:en, :bar, :foo) + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, :'baz.buz', :'foo.bar') + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, 'baz.buz', 'foo.bar') + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, %w(baz buz), %w(foo bar)) + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, [:baz, :buz], [:foo, :bar]) + end + + test "normalize_keys discards empty keys" do + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, :'baz..buz', :'foo..bar') + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, :'baz......buz', :'foo......bar') + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, ['baz', nil, '', 'buz'], ['foo', nil, '', 'bar']) + end + + test "normalize_keys uses a given separator" do + assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, :'baz|buz', :'foo|bar', '|') + end + + test "can set the exception_handler" do + begin + previous_exception_handler = I18n.exception_handler + assert_nothing_raised { I18n.exception_handler = :custom_exception_handler } + ensure + I18n.exception_handler = previous_exception_handler + end + end + + test "uses a custom exception handler set to I18n.exception_handler" do + begin + previous_exception_handler = I18n.exception_handler + I18n.exception_handler = :custom_exception_handler + I18n.expects(:custom_exception_handler) + I18n.translate :bogus + ensure + I18n.exception_handler = previous_exception_handler + end + end + + test "uses a custom exception handler passed as an option" do + I18n.expects(:custom_exception_handler) + I18n.translate(:bogus, :exception_handler => :custom_exception_handler) + end + + test "delegates translate calls to the backend" do + I18n.backend.expects(:translate).with('de', :foo, {}) + I18n.translate :foo, :locale => 'de' + end + + test "delegates localize calls to the backend" do + I18n.backend.expects(:localize).with('de', :whatever, :default, {}) + I18n.localize :whatever, :locale => 'de' + end + + test "translate given no locale uses the current locale" do + I18n.backend.expects(:translate).with(:en, :foo, {}) + I18n.translate :foo + end + + test "translate works with nested symbol keys" do + assert_equal ".", I18n.t(:'currency.format.separator') + end + + test "translate works with nested string keys" do + assert_equal ".", I18n.t('currency.format.separator') + end + + test "translate with an array as a scope works" do + assert_equal ".", I18n.t(:separator, :scope => %w(currency format)) + end + + test "translate with an array containing dot separated strings as a scope works" do + assert_equal ".", I18n.t(:separator, :scope => ['currency.format']) + end + + test "translate with an array of keys and a dot separated string as a scope works" do + assert_equal [".", ","], I18n.t(%w(separator delimiter), :scope => 'currency.format') + end + + test "translate with an array of dot separated keys and a scope works" do + assert_equal [".", ","], I18n.t(%w(format.separator format.delimiter), :scope => 'currency') + end + + # def test_translate_given_no_args_raises_missing_translation_data + # assert_equal "translation missing: en, no key", I18n.t + # end + + test "translate given a bogus key returns an error message" do + assert_equal "translation missing: en.bogus", I18n.t(:bogus) + end + + test "translate given an empty string as a key raises an I18n::ArgumentError" do + assert_raise(I18n::ArgumentError) { I18n.t("") } + end + + test "localize given nil raises an I18n::ArgumentError" do + assert_raise(I18n::ArgumentError) { I18n.l nil } + end + + test "localize givan an Object raises an I18n::ArgumentError" do + assert_raise(I18n::ArgumentError) { I18n.l Object.new } + end + + test "can use a lambda as an exception handler" do + begin + previous_exception_handler = I18n.exception_handler + I18n.exception_handler = Proc.new { |exception, locale, key, options| key } + assert_equal :test_proc_handler, I18n.translate(:test_proc_handler) + ensure + I18n.exception_handler = previous_exception_handler + end + end + + test "can use an object responding to #call as an exception handler" do + begin + previous_exception_handler = I18n.exception_handler + I18n.exception_handler = Class.new do + def call(exception, locale, key, options); key; end + end.new + assert_equal :test_proc_handler, I18n.translate(:test_proc_handler) + ensure + I18n.exception_handler = previous_exception_handler + end + end + + test "I18n.with_locale temporarily sets the given locale" do + store_translations(:en, :foo => 'Foo in :en') + store_translations(:de, :foo => 'Foo in :de') + store_translations(:pl, :foo => 'Foo in :pl') + + I18n.with_locale { assert_equal [:en, 'Foo in :en'], [I18n.locale, I18n.t(:foo)] } + I18n.with_locale(:de) { assert_equal [:de, 'Foo in :de'], [I18n.locale, I18n.t(:foo)] } + I18n.with_locale(:pl) { assert_equal [:pl, 'Foo in :pl'], [I18n.locale, I18n.t(:foo)] } + I18n.with_locale(:en) { assert_equal [:en, 'Foo in :en'], [I18n.locale, I18n.t(:foo)] } + + assert_equal I18n.default_locale, I18n.locale + end + + test "I18n.with_locale resets the locale in case of errors" do + assert_raise(I18n::ArgumentError) { I18n.with_locale(:pl) { raise I18n::ArgumentError } } + assert_equal I18n.default_locale, I18n.locale + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/fallbacks_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/fallbacks_test.rb new file mode 100644 index 0000000..951016a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/fallbacks_test.rb @@ -0,0 +1,124 @@ +require 'test_helper' + +include I18n::Locale + +class I18nFallbacksDefaultsTest < Test::Unit::TestCase + def teardown + I18n.default_locale = :en + end + + test "defaults reflect the I18n.default_locale if no default has been set manually" do + I18n.default_locale = :'en-US' + fallbacks = Fallbacks.new + assert_equal [:'en-US', :en], fallbacks.defaults + end + + test "defaults reflect a manually passed default locale if any" do + fallbacks = Fallbacks.new(:'fi-FI') + assert_equal [:'fi-FI', :fi], fallbacks.defaults + I18n.default_locale = :'de-DE' + assert_equal [:'fi-FI', :fi], fallbacks.defaults + end + + test "defaults allows to set multiple defaults" do + fallbacks = Fallbacks.new(:'fi-FI', :'se-FI') + assert_equal [:'fi-FI', :fi, :'se-FI', :se], fallbacks.defaults + end +end + +class I18nFallbacksComputationTest < Test::Unit::TestCase + def setup + @fallbacks = Fallbacks.new(:'en-US') + end + + test "with no mappings defined it returns [:es, :en-US] for :es" do + assert_equal [:es, :"en-US", :en], @fallbacks[:es] + end + + test "with no mappings defined it returns [:es-ES, :es, :en-US] for :es-ES" do + assert_equal [:"es-ES", :es, :"en-US", :en], @fallbacks[:"es-ES"] + end + + test "with no mappings defined it returns [:es-MX, :es, :en-US] for :es-MX" do + assert_equal [:"es-MX", :es, :"en-US", :en], @fallbacks[:"es-MX"] + end + + test "with no mappings defined it returns [:es-Latn-ES, :es-Latn, :es, :en-US] for :es-Latn-ES" do + assert_equal [:"es-Latn-ES", :"es-Latn", :es, :"en-US", :en], @fallbacks[:'es-Latn-ES'] + end + + test "with no mappings defined it returns [:en, :en-US] for :en" do + assert_equal [:en, :"en-US"], @fallbacks[:en] + end + + test "with no mappings defined it returns [:en-US, :en] for :en-US (special case: locale == default)" do + assert_equal [:"en-US", :en], @fallbacks[:"en-US"] + end + + # Most people who speak Catalan also live in Spain, so it is safe to assume + # that they also speak Spanish as spoken in Spain. + test "with a Catalan mapping defined it returns [:ca, :es-ES, :es, :en-US] for :ca" do + @fallbacks.map(:ca => :"es-ES") + assert_equal [:ca, :"es-ES", :es, :"en-US", :en], @fallbacks[:ca] + end + + test "with a Catalan mapping defined it returns [:ca-ES, :ca, :es-ES, :es, :en-US] for :ca-ES" do + @fallbacks.map(:ca => :"es-ES") + assert_equal [:"ca-ES", :ca, :"es-ES", :es, :"en-US", :en], @fallbacks[:"ca-ES"] + end + + # People who speak Arabic as spoken in Palestine often times also speak + # Hebrew as spoken in Israel. However it is in no way safe to assume that + # everybody who speaks Arabic also speaks Hebrew. + + test "with a Hebrew mapping defined it returns [:ar, :en-US] for :ar" do + @fallbacks.map(:"ar-PS" => :"he-IL") + assert_equal [:ar, :"en-US", :en], @fallbacks[:ar] + end + + test "with a Hebrew mapping defined it returns [:ar-EG, :ar, :en-US] for :ar-EG" do + @fallbacks.map(:"ar-PS" => :"he-IL") + assert_equal [:"ar-EG", :ar, :"en-US", :en], @fallbacks[:"ar-EG"] + end + + test "with a Hebrew mapping defined it returns [:ar-PS, :ar, :he-IL, :he, :en-US] for :ar-PS" do + @fallbacks.map(:"ar-PS" => :"he-IL") + assert_equal [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en], @fallbacks[:"ar-PS"] + end + + # Sami people live in several scandinavian countries. In Finnland many people + # know Swedish and Finnish. Thus, it can be assumed that Sami living in + # Finnland also speak Swedish and Finnish. + + test "with a Sami mapping defined it returns [:sms-FI, :sms, :se-FI, :se, :fi-FI, :fi, :en-US] for :sms-FI" do + @fallbacks.map(:sms => [:"se-FI", :"fi-FI"]) + assert_equal [:"sms-FI", :sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en], @fallbacks[:"sms-FI"] + end + + # Austrian people understand German as spoken in Germany + + test "with a German mapping defined it returns [:de, :en-US] for de" do + @fallbacks.map(:"de-AT" => :"de-DE") + assert_equal [:de, :"en-US", :en], @fallbacks[:"de"] + end + + test "with a German mapping defined it returns [:de-DE, :de, :en-US] for de-DE" do + @fallbacks.map(:"de-AT" => :"de-DE") + assert_equal [:"de-DE", :de, :"en-US", :en], @fallbacks[:"de-DE"] + end + + test "with a German mapping defined it returns [:de-AT, :de, :de-DE, :en-US] for de-AT" do + @fallbacks.map(:"de-AT" => :"de-DE") + assert_equal [:"de-AT", :de, :"de-DE", :"en-US", :en], @fallbacks[:"de-AT"] + end + + # Mapping :de => :en, :he => :en + + test "with a mapping :de => :en, :he => :en defined it returns [:de, :en] for :de" do + assert_equal [:de, :"en-US", :en], @fallbacks[:de] + end + + test "with a mapping :de => :en, :he => :en defined it [:he, :en] for :de" do + assert_equal [:he, :"en-US", :en], @fallbacks[:he] + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/tag/rfc4646_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/tag/rfc4646_test.rb new file mode 100644 index 0000000..1118049 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/tag/rfc4646_test.rb @@ -0,0 +1,142 @@ +# encoding: utf-8 +require 'test_helper' + +class I18nLocaleTagRfc4646ParserTest < Test::Unit::TestCase + include I18n::Locale + + test "Rfc4646::Parser given a valid tag 'de' returns an array of subtags" do + assert_equal ['de', nil, nil, nil, nil, nil, nil], Tag::Rfc4646::Parser.match('de') + end + + test "Rfc4646::Parser given a valid tag 'de-DE' returns an array of subtags" do + assert_equal ['de', nil, 'DE', nil, nil, nil, nil], Tag::Rfc4646::Parser.match('de-DE') + end + + test "Rfc4646::Parser given a valid lowercase tag 'de-latn-de-variant-x-phonebk' returns an array of subtags" do + assert_equal ['de', 'latn', 'de', 'variant', nil, 'x-phonebk', nil], Tag::Rfc4646::Parser.match('de-latn-de-variant-x-phonebk') + end + + test "Rfc4646::Parser given a valid uppercase tag 'DE-LATN-DE-VARIANT-X-PHONEBK' returns an array of subtags" do + assert_equal ['DE', 'LATN', 'DE', 'VARIANT', nil, 'X-PHONEBK', nil], Tag::Rfc4646::Parser.match('DE-LATN-DE-VARIANT-X-PHONEBK') + end + + test "Rfc4646::Parser given an invalid tag 'a-DE' it returns false" do + assert_equal false, Tag::Rfc4646::Parser.match('a-DE') + end + + test "Rfc4646::Parser given an invalid tag 'de-419-DE' it returns false" do + assert_equal false, Tag::Rfc4646::Parser.match('de-419-DE') + end +end + +# Tag for the locale 'de-Latn-DE-Variant-a-ext-x-phonebk-i-klingon' + +class I18nLocaleTagSubtagsTest < Test::Unit::TestCase + include I18n::Locale + + def setup + subtags = %w(de Latn DE variant a-ext x-phonebk i-klingon) + @tag = Tag::Rfc4646.new(*subtags) + end + + test "returns 'de' as the language subtag in lowercase" do + assert_equal 'de', @tag.language + end + + test "returns 'Latn' as the script subtag in titlecase" do + assert_equal 'Latn', @tag.script + end + + test "returns 'DE' as the region subtag in uppercase" do + assert_equal 'DE', @tag.region + end + + test "returns 'variant' as the variant subtag in lowercase" do + assert_equal 'variant', @tag.variant + end + + test "returns 'a-ext' as the extension subtag" do + assert_equal 'a-ext', @tag.extension + end + + test "returns 'x-phonebk' as the privateuse subtag" do + assert_equal 'x-phonebk', @tag.privateuse + end + + test "returns 'i-klingon' as the grandfathered subtag" do + assert_equal 'i-klingon', @tag.grandfathered + end + + test "returns a formatted tag string from #to_s" do + assert_equal 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon', @tag.to_s + end + + test "returns an array containing the formatted subtags from #to_a" do + assert_equal %w(de Latn DE variant a-ext x-phonebk i-klingon), @tag.to_a + end +end + +# Tag inheritance + +class I18nLocaleTagSubtagsTest < Test::Unit::TestCase + test "#parent returns 'de-Latn-DE-variant-a-ext-x-phonebk' as the parent of 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon'" do + tag = Tag::Rfc4646.new(*%w(de Latn DE variant a-ext x-phonebk i-klingon)) + assert_equal 'de-Latn-DE-variant-a-ext-x-phonebk', tag.parent.to_s + end + + test "#parent returns 'de-Latn-DE-variant-a-ext' as the parent of 'de-Latn-DE-variant-a-ext-x-phonebk'" do + tag = Tag::Rfc4646.new(*%w(de Latn DE variant a-ext x-phonebk)) + assert_equal 'de-Latn-DE-variant-a-ext', tag.parent.to_s + end + + test "#parent returns 'de-Latn-DE-variant' as the parent of 'de-Latn-DE-variant-a-ext'" do + tag = Tag::Rfc4646.new(*%w(de Latn DE variant a-ext)) + assert_equal 'de-Latn-DE-variant', tag.parent.to_s + end + + test "#parent returns 'de-Latn-DE' as the parent of 'de-Latn-DE-variant'" do + tag = Tag::Rfc4646.new(*%w(de Latn DE variant)) + assert_equal 'de-Latn-DE', tag.parent.to_s + end + + test "#parent returns 'de-Latn' as the parent of 'de-Latn-DE'" do + tag = Tag::Rfc4646.new(*%w(de Latn DE)) + assert_equal 'de-Latn', tag.parent.to_s + end + + test "#parent returns 'de' as the parent of 'de-Latn'" do + tag = Tag::Rfc4646.new(*%w(de Latn)) + assert_equal 'de', tag.parent.to_s + end + + # TODO RFC4647 says: "If no language tag matches the request, the "default" value is returned." + # where should we set the default language? + # test "#parent returns '' as the parent of 'de'" do + # tag = Tag::Rfc4646.new *%w(de) + # assert_equal '', tag.parent.to_s + # end + + test "#parent returns an array of 5 parents for 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon'" do + parents = %w(de-Latn-DE-variant-a-ext-x-phonebk-i-klingon + de-Latn-DE-variant-a-ext-x-phonebk + de-Latn-DE-variant-a-ext + de-Latn-DE-variant + de-Latn-DE + de-Latn + de) + tag = Tag::Rfc4646.new(*%w(de Latn DE variant a-ext x-phonebk i-klingon)) + assert_equal parents, tag.self_and_parents.map(&:to_s) + end + + test "returns an array of 5 parents for 'de-Latn-DE-variant-a-ext-x-phonebk-i-klingon'" do + parents = %w(de-Latn-DE-variant-a-ext-x-phonebk-i-klingon + de-Latn-DE-variant-a-ext-x-phonebk + de-Latn-DE-variant-a-ext + de-Latn-DE-variant + de-Latn-DE + de-Latn + de) + tag = Tag::Rfc4646.new(*%w(de Latn DE variant a-ext x-phonebk i-klingon)) + assert_equal parents, tag.self_and_parents.map(&:to_s) + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/tag/simple_test.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/tag/simple_test.rb new file mode 100644 index 0000000..ed2f76b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/locale/tag/simple_test.rb @@ -0,0 +1,32 @@ +# encoding: utf-8 +require 'test_helper' + +class I18nLocaleTagSimpleTest < Test::Unit::TestCase + include I18n::Locale + + test "returns 'de' as the language subtag in lowercase" do + assert_equal %w(de Latn DE), Tag::Simple.new('de-Latn-DE').subtags + end + + test "returns a formatted tag string from #to_s" do + assert_equal 'de-Latn-DE', Tag::Simple.new('de-Latn-DE').to_s + end + + test "returns an array containing the formatted subtags from #to_a" do + assert_equal %w(de Latn DE), Tag::Simple.new('de-Latn-DE').to_a + end + + # Tag inheritance + + test "#parent returns 'de-Latn' as the parent of 'de-Latn-DE'" do + assert_equal 'de-Latn', Tag::Simple.new('de-Latn-DE').parent.to_s + end + + test "#parent returns 'de' as the parent of 'de-Latn'" do + assert_equal 'de', Tag::Simple.new('de-Latn').parent.to_s + end + + test "#self_and_parents returns an array of 3 tags for 'de-Latn-DE'" do + assert_equal %w(de-Latn-DE de-Latn de), Tag::Simple.new('de-Latn-DE').self_and_parents.map { |tag| tag.to_s} + end +end diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/run_all.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/run_all.rb new file mode 100644 index 0000000..0c31db7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/run_all.rb @@ -0,0 +1,21 @@ +def bundle_check + `bundle check` == "The Gemfile's dependencies are satisfied\n" +end + +command = 'ruby -w -Ilib -Itest test/all.rb' +gemfiles = %w(ci/Gemfile.rails-3.x ci/Gemfile.rails-2.3.x ci/Gemfile.no-rails) + +results = gemfiles.map do |gemfile| + puts "BUNDLE_GEMFILE=#{gemfile}" + ENV['BUNDLE_GEMFILE'] = gemfile + + unless bundle_check + puts "bundle install" + system('bundle install') + end + + puts command + system('ruby -w -Ilib -Itest test/all.rb') +end + +exit(results.inject(true) { |a, b| a && b }) diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/de.po b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/de.po new file mode 100644 index 0000000..c162e87 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/de.po @@ -0,0 +1,72 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: version 0.0.1\n" +"POT-Creation-Date: 2009-02-26 19:50+0100\n" +"PO-Revision-Date: 2009-02-18 14:53+0100\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +# #: app/helpers/translation_helper.rb:3 +# msgid "%{relative_time} ago" +# msgstr "vor %{relative_time}" + +#: app/views/cars/show.html.erb:5 +msgid "Axis" +msgid_plural "Axis" +msgstr[0] "Achse" +msgstr[1] "Achsen" + +#: app/controllers/cars_controller.rb:47 +msgid "Car was successfully created." +msgstr "Auto wurde erfolgreich gespeichert" + +#: app/controllers/cars_controller.rb:64 +msgid "Car was successfully updated." +msgstr "Auto wurde erfolgreich aktualisiert" + +#: app/views/cars/show.html.erb:1 locale/model_attributes.rb:3 +msgid "Car|Model" +msgstr "Modell" + +#: app/views/cars/show.html.erb:3 locale/model_attributes.rb:4 +msgid "Car|Wheels count" +msgstr "Räderzahl" + +#: app/views/cars/show.html.erb:7 +msgid "Created" +msgstr "Erstellt" + +#: app/views/cars/show.html.erb:9 +msgid "Month" +msgstr "Monat" + +#: locale/model_attributes.rb:2 +msgid "car" +msgstr "Auto" + +#: locale/testlog_phrases.rb:2 +msgid "this is a dynamic translation which was found thorugh gettext_test_log!" +msgstr "" +"Dies ist eine dynamische Ãœbersetzung, die durch gettext_test_log " +"gefunden wurde!" + +#: app/views/cars/nowhere_really +msgid "Car|wheel" +msgid_plural "Car|wheels" +msgstr[0] "Rad" +msgstr[1] "Räder" + +msgid "On %{count} wheel." +msgid_plural "On %{count} wheels." +msgstr[0] "Auf %{count} Achse." +msgstr[1] "Auf %{count} Achsen." diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/en.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/en.rb new file mode 100644 index 0000000..e847d10 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/en.rb @@ -0,0 +1,3 @@ +# encoding: utf-8 + +{ :en => { :fuh => { :bah => "bas" } } } \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/en.yml b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/en.yml new file mode 100644 index 0000000..25f5bb6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/en.yml @@ -0,0 +1,3 @@ +en: + foo: + bar: baz \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/invalid/empty.yml b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/invalid/empty.yml new file mode 100644 index 0000000..d002480 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/invalid/empty.yml @@ -0,0 +1 @@ +en: \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/plurals.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/plurals.rb new file mode 100644 index 0000000..d1ea34e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_data/locales/plurals.rb @@ -0,0 +1,113 @@ +# encoding: utf-8 + +{ + :af => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :am => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :ar => { :i18n => { :plural => { :keys => [:zero, :one, :two, :few, :many, :other], :rule => lambda { |n| n == 0 ? :zero : n == 1 ? :one : n == 2 ? :two : [3, 4, 5, 6, 7, 8, 9, 10].include?(n % 100) ? :few : [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99].include?(n % 100) ? :many : :other } } } }, + :az => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :be => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :bg => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :bh => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :bn => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :bo => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :bs => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :ca => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :cs => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n == 1 ? :one : [2, 3, 4].include?(n) ? :few : :other } } } }, + :cy => { :i18n => { :plural => { :keys => [:one, :two, :many, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : n == 8 || n == 11 ? :many : :other } } } }, + :da => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :de => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :dz => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :el => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :en => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :eo => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :es => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :et => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :eu => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :fa => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :fi => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :fil => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :fo => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :fr => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n && n != 2 ? :one : :other } } } }, + :fur => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :fy => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ga => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :gl => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :gu => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :guw => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :ha => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :he => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :hi => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :hr => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :hu => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :id => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :is => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :it => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :iw => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ja => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :jv => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :ka => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :km => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :kn => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :ko => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :ku => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :lb => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ln => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :lt => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n % 10 == 1 && ![11, 12, 13, 14, 15, 16, 17, 18, 19].include?(n % 100) ? :one : [2, 3, 4, 5, 6, 7, 8, 9].include?(n % 10) && ![11, 12, 13, 14, 15, 16, 17, 18, 19].include?(n % 100) ? :few : :other } } } }, + :lv => { :i18n => { :plural => { :keys => [:zero, :one, :other], :rule => lambda { |n| n == 0 ? :zero : n % 10 == 1 && n % 100 != 11 ? :one : :other } } } }, + :mg => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :mk => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n % 10 == 1 ? :one : :other } } } }, + :ml => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :mn => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :mo => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n == 1 ? :one : n == 0 ? :few : :other } } } }, + :mr => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ms => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :mt => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n == 1 ? :one : n == 0 || [2, 3, 4, 5, 6, 7, 8, 9, 10].include?(n % 100) ? :few : [11, 12, 13, 14, 15, 16, 17, 18, 19].include?(n % 100) ? :many : :other } } } }, + :my => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :nah => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :nb => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ne => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :nl => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :nn => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :no => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :nso => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :om => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :or => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :pa => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :pap => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :pl => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n == 1 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) && ![22, 23, 24].include?(n % 100) ? :few : :other } } } }, + :ps => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :pt => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :"pt-PT" => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ro => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n == 1 ? :one : n == 0 ? :few : :other } } } }, + :ru => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :se => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :sh => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :sk => { :i18n => { :plural => { :keys => [:one, :few, :other], :rule => lambda { |n| n == 1 ? :one : [2, 3, 4].include?(n) ? :few : :other } } } }, + :sl => { :i18n => { :plural => { :keys => [:one, :two, :few, :other], :rule => lambda { |n| n % 100 == 1 ? :one : n % 100 == 2 ? :two : [3, 4].include?(n % 100) ? :few : :other } } } }, + :sma => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :smi => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :smj => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :smn => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :sms => { :i18n => { :plural => { :keys => [:one, :two, :other], :rule => lambda { |n| n == 1 ? :one : n == 2 ? :two : :other } } } }, + :so => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :sq => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :sr => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :sv => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :sw => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :ta => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :te => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :th => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :ti => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :tk => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :tl => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :to => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :tr => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :uk => { :i18n => { :plural => { :keys => [:one, :few, :many, :other], :rule => lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other } } } }, + :ur => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } }, + :vi => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :wa => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, + :yo => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :zh => { :i18n => { :plural => { :keys => [:other], :rule => lambda { |n| :other } } } }, + :zu => { :i18n => { :plural => { :keys => [:one, :other], :rule => lambda { |n| n == 1 ? :one : :other } } } } +} + diff --git a/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_helper.rb b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_helper.rb new file mode 100644 index 0000000..982dd2d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/i18n-0.6.0/test/test_helper.rb @@ -0,0 +1,56 @@ +$KCODE = 'u' if RUBY_VERSION <= '1.9' + +require 'rubygems' +require 'test/unit' + +# Do not load the i18n gem from libraries like active_support. +# +# This is required for testing against Rails 2.3 because active_support/vendor.rb#24 tries +# to load I18n using the gem method. Instead, we want to test the local library of course. +alias :gem_for_ruby_19 :gem # for 1.9. gives a super ugly seg fault otherwise +def gem(gem_name, *version_requirements) + gem_name =='i18n' ? puts("skipping loading the i18n gem ...") : super +end + +require 'bundler/setup' +require 'i18n' +require 'mocha' +require 'test_declarative' + +class Test::Unit::TestCase + def teardown + I18n.locale = nil + I18n.default_locale = :en + I18n.load_path = [] + I18n.available_locales = nil + I18n.backend = nil + end + + def translations + I18n.backend.instance_variable_get(:@translations) + end + + def store_translations(*args) + data = args.pop + locale = args.pop || :en + I18n.backend.store_translations(locale, data) + end + + def locales_dir + File.dirname(__FILE__) + '/test_data/locales' + end +end + +module Kernel + def setup_rufus_tokyo + require 'rufus/tokyo' + rescue LoadError => e + puts "can't use KeyValue backend because: #{e.message}" + end +end + +Object.class_eval do + def meta_class + class << self; self; end + end +end unless Object.method_defined?(:meta_class) diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/.gitignore b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/.gitignore new file mode 100644 index 0000000..677c465 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/.gitignore @@ -0,0 +1 @@ +.bundle diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/CHANGELOG b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/CHANGELOG new file mode 100644 index 0000000..6fa3ce2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/CHANGELOG @@ -0,0 +1,142 @@ +# Version 1.3.0 + +* Added support for multiple polymorphic optional nesting +* Fix nested namespace in mountable apps +* Added support for rails 3.1 new mass assignment conventions +* Turn InheritedResources::Base into a reloadable constant to fix reloading issues + +# Version 1.2.2 + +* Fix a bug in params parsing +* Call .scoped only if it is available + +# Version 1.2.1 + +* Fix a bug with namespaces +* Use Post.scoped instead of Post.all in collection + +# Version 1.2 + +* Improved lookup for namespaces (by github.com/Sirupsen) +* Support to custom actions (by github.com/lda) +* Rails 3.1 compatibility (by github.com/etehtsea) + +# Version 1.1 + +* Rails 3 compatible + +# Version 1.0 + +* responders was removed from InheritedResources core and is a dependency. To install it, please do: + + sudo gem install responders + +* has_scope was removed from InheritedResources core and is now available as a standalone gem. + To install it, please do: + + sudo gem install has_scope + +# Version 0.9 + +* Allow dual blocks in destroy; +* Added :if and :unless to has_scope (thanks to Jack Danger); +* Added create_resource, update_resource and delete_resource hooks (thanks to Carlos Antonio da Silva); +* Backported ActionController::Responder from Rails 3; +* Added parent_url helper; +* Added association_chain helper (as suggested by http://github.com/emmanuel); + +# Version 0.8 + +* Fixed a small bug on optional belongs to with namespaced controllers. +* Allow a parameter to be given to collection_url in polymorphic cases to replace + the parent. +* Allow InheritedResources to be called without inheritance. +* Ensure that controllers that inherit from a controller with InheritedResources + works properly. + +# Version 0.7 + +* Allow procs as default value in has scope to be able to use values from session, for example. +* Allow blocks with arity 0 or -1 to be given as the redirect url: + + def destroy + destroy!{ project_url(@project) } + end + +* Allow interpolation_options to be set in the application controller. +* Added has_scope to controller (an interface for named_scopes). +* Added polymorphic_belongs_to, optional_belongs_to and singleton_belongs_to + as quick methods. +* Only load belongs_to, singleton and polymorphic helpers if they are actually + required. base_helpers, class_methods, dumb_responder and url_helpers are loaded + when you inherited from base for the first time. + +# Version 0.6 + +* Ensure that the default template is not rendered if the default_template_format + is not accepted. This is somehow related with the security breach report: + + http://www.rorsecurity.info/journal/2009/4/24/hidden-actions-render-templates.html + + IR forbids based on mime types. For example: respond_to :html, :except => :index + ensures that the index.html.erb view is not rendered, making your IR controllers + safer. + +* Fixed a bug that happens only when format.xml is given to blocks and then it + acts as default, instead of format.html. +* Fixed a strange bug where when you have create.html.erb or update.html.erb, + it makes IE6 and IE7 return unprocessable entity (because they send Mime::ALL). +* Stop rescueing any error when constantizing the resource class and allow + route_prefix to be nil. +* Cleaned up tests and responder structure. Whenever you pass a block to aliases + and this block responds to the request, the other blocks are not parsed improving performance. +* [BACKWARDS INCOMPATIBLE] By default, Inherited Resources respond only :html requests. +* Added a quick way to overwrite the redirect to url in :create, :update and :destroy. + +# Version 0.5 + +* Decoupled routes name from :instance_name and :collection_name. This way we + have more flexibility. Use route_instance_name and route_collection_name to + to change routes. +* Avoid calling human_name on nil when a resource class is not defined. +* Only call I18n if it's defined. + +# Version 0.4 + +* Dealing with namespaced controllers out of the box. +* Added support to namespaced routes through :route_prefix. +* Added fix when resource_url is not defined. +* Added better handling for namespaced controllers. +* Added flash messages scoped by namespaced controllers. +* Deprecated {{resource}} in I18n, use {{resource_name}} instead. +* rspec bug fix is not automatically required anymore. User has to do it + explicitly. +* Added a file which fix a rspec bug when render is called inside a method + which receives a block. +* parent? does not take begin_of_association_chain into account anymore +* Added options to url helpers. +* Added :optional to belongs_to associations. It allows you to deal with + categories/1/products/2 and /products/2 with just one controller. +* Cleaned up tests. + +# Version 0.3 + +* Minor bump after three bug fixes. +* Bug fix when showing warning of constant redefinition. +* Bug fix with ApplicationController not being unloaded properly on development. +* Bug fix when having root singleton resources. Calling collection_url would + raise "NoMethodError _url", not it will call root_url. +* More comments on UrlHelpers. + +# Version 0.2 + +* Bug fix when ApplicationController is already loaded when we load respond_to. +* Added support success/failure blocks. +* Eager loading of files to work properly in multithreaded environments. + +# Version 0.1 + +* Added more helper_methods. +* Added Rails 2.3.0 and changed tests to work with ActionController::TestCase. +* First release. Support to I18n, singleton controllers, polymorphic +controllers, belongs_to, nested_belongs_to and url helpers. diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Gemfile b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Gemfile new file mode 100644 index 0000000..6e25dbc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Gemfile @@ -0,0 +1,12 @@ +source "http://rubygems.org" + +gem "rails", "3.1.0.rc4" +gem "responders", "~> 0.6.0" +gem "has_scope", "~> 0.5.0" +gem "mocha" + +if RUBY_VERSION < "1.9" + gem "ruby-debug" +else + gem "test-unit" +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Gemfile.lock b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Gemfile.lock new file mode 100644 index 0000000..f2a574d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Gemfile.lock @@ -0,0 +1,104 @@ +GEM + remote: http://rubygems.org/ + specs: + actionmailer (3.1.0.rc4) + actionpack (= 3.1.0.rc4) + mail (~> 2.3.0) + actionpack (3.1.0.rc4) + activemodel (= 3.1.0.rc4) + activesupport (= 3.1.0.rc4) + builder (~> 3.0.0) + erubis (~> 2.7.0) + i18n (~> 0.6) + rack (~> 1.3.0) + rack-cache (~> 1.0.1) + rack-mount (~> 0.8.1) + rack-test (~> 0.6.0) + sprockets (~> 2.0.0.beta.10) + tzinfo (~> 0.3.27) + activemodel (3.1.0.rc4) + activesupport (= 3.1.0.rc4) + bcrypt-ruby (~> 2.1.4) + builder (~> 3.0.0) + i18n (~> 0.6) + activerecord (3.1.0.rc4) + activemodel (= 3.1.0.rc4) + activesupport (= 3.1.0.rc4) + arel (~> 2.1.1) + tzinfo (~> 0.3.27) + activeresource (3.1.0.rc4) + activemodel (= 3.1.0.rc4) + activesupport (= 3.1.0.rc4) + activesupport (3.1.0.rc4) + multi_json (~> 1.0) + arel (2.1.1) + bcrypt-ruby (2.1.4) + builder (3.0.0) + columnize (0.3.4) + erubis (2.7.0) + has_scope (0.5.0) + hike (1.1.0) + i18n (0.6.0) + linecache (0.46) + rbx-require-relative (> 0.0.4) + mail (2.3.0) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.16) + mocha (0.9.8) + rake + multi_json (1.0.3) + polyglot (0.3.1) + rack (1.3.0) + rack-cache (1.0.2) + rack (>= 0.4) + rack-mount (0.8.1) + rack (>= 1.0.0) + rack-ssl (1.3.2) + rack + rack-test (0.6.0) + rack (>= 1.0) + rails (3.1.0.rc4) + actionmailer (= 3.1.0.rc4) + actionpack (= 3.1.0.rc4) + activerecord (= 3.1.0.rc4) + activeresource (= 3.1.0.rc4) + activesupport (= 3.1.0.rc4) + bundler (~> 1.0) + railties (= 3.1.0.rc4) + railties (3.1.0.rc4) + actionpack (= 3.1.0.rc4) + activesupport (= 3.1.0.rc4) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (~> 0.14.6) + rake (0.8.7) + rbx-require-relative (0.0.5) + rdoc (3.6.1) + responders (0.6.4) + ruby-debug (0.10.4) + columnize (>= 0.1) + ruby-debug-base (~> 0.10.4.0) + ruby-debug-base (0.10.4) + linecache (>= 0.3) + sprockets (2.0.0.beta.10) + hike (~> 1.0) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + thor (0.14.6) + tilt (1.3.2) + treetop (1.4.9) + polyglot (>= 0.3.1) + tzinfo (0.3.28) + +PLATFORMS + ruby + +DEPENDENCIES + has_scope (~> 0.5.0) + mocha + rails (= 3.1.0.rc4) + responders (~> 0.6.0) + ruby-debug diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/MIT-LICENSE b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/MIT-LICENSE new file mode 100644 index 0000000..5c0b9cb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2009 José Valim http://blog.plataformatec.com.br + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/README.rdoc b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/README.rdoc new file mode 100644 index 0000000..94178c9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/README.rdoc @@ -0,0 +1,541 @@ +== Inherited Resources + +Inherited Resources speeds up development by making your controllers inherit +all restful actions so you just have to focus on what is important. It makes +your controllers more powerful and cleaner at the same time. + +Plus, making your controllers follow a pattern, it helps you to write better +code by following fat models and skinny controllers convention. There are +two screencasts available besides this README: + +* http://railscasts.com/episodes/230-inherited-resources +* http://akitaonrails.com/2009/09/01/screencast-real-thin-restful-controllers-with-inherited-resources + +== Installation + +=== Rails 3 + +You can let bundler install Inherited Resources by adding this line to your application's Gemfile: + + gem 'inherited_resources' + +And then execute: + + bundle install + +Or install it yourself as: + + gem install inherited_resources + +=== Rails 2.3.x + +If you want to use the Rails 2.3.x version, you should install: + + gem install inherited_resources --version=1.0.6 + +Or checkout from the v1.0 branch: + + http://github.com/josevalim/inherited_resources/tree/v1.0 + +== HasScope + +Since Inherited Resources 1.0, has_scope is not part of its core anymore but +a gem dependency. Be sure to check the documentation to see how you can use it: + + http://github.com/plataformatec/has_scope + +And it can be installed as: + + gem install has_scope + +== Responders + +Since Inherited Resources 1.0, responders are not part of its core anymore, +but is set as Inherited Resources dependency and it's used by default by +InheritedResources controllers. Be sure to check the documentation to see +how it will change your application: + + http://github.com/plataformatec/responders + +And it can be installed as: + + gem install responders + +Using responders will set the flash message to :notice and :alert. You can change +that through the following configuration value: + + InheritedResources.flash_keys = [ :success, :failure ] + +Notice the CollectionResponder won't work with InheritedResources, as InheritedResources hardcodes the redirect path based on the current scope (like belongs to, polymorphic associations, etc). + +== Basic Usage + +To use Inherited Resources you just have to inherit (duh) it: + + class ProjectsController < InheritedResources::Base + end + +And all actions are defined and working, check it! Your projects collection +(in the index action) is still available in the instance variable @projects +and your project resource (all other actions) is available as @project. + +The next step is to define which mime types this controller provides: + + class ProjectsController < InheritedResources::Base + respond_to :html, :xml, :json + end + +You can also specify them based per action: + + class ProjectsController < InheritedResources::Base + respond_to :html, :xml, :json + respond_to :js, :only => :create + respond_to :iphone, :except => [ :edit, :update ] + end + +For each request, it first checkes if the "controller/action.format" file is +available (for example "projects/create.xml") and if it's not, it checks if +the resource respond to :to_format (in this case, :to_xml). Otherwise returns 404. + +Another option is to specify which actions the controller will inherit from +the InheritedResources::Base: + + class ProjectsController < InheritedResources::Base + actions :index, :show, :new, :create + end + +Or: + + class ProjectsController < InheritedResources::Base + actions :all, :except => [ :edit, :update, :destroy ] + end + +In your views, you will get the following helpers: + + resource #=> @project + collection #=> @projects + resource_class #=> Project + +As you might expect, collection (@projects instance variable) is only available +on index actions. + +If for some reason you cannot inherit from InheritedResources::Base, you can +call inherit_resources in your controller class scope: + + class AccountsController < ApplicationController + inherit_resources + end + +== Overwriting defaults + +Whenever you inherit from InheritedResources, several defaults are assumed. +For example you can have an AccountsController to account management while the +resource is an User: + + class AccountsController < InheritedResources::Base + defaults :resource_class => User, :collection_name => 'users', :instance_name => 'user' + end + +In the case above, in your views you will have @users and @user variables, but +the routes used will still be accounts_url and account_url. If you plan also to +change the routes, you can use :route_collection_name and :route_instance_name. + +Namespaced controllers work out of the box, but if you need to specify a +different route prefix, you can do the following: + + class Administrators::PeopleController < InheritedResources::Base + defaults :route_prefix => 'admin' + end + +Then your named routes will be: 'admin_people_url', 'admin_person_url' instead +of 'administrators_people_url' and 'administrators_person_url'. + +If you want to customize how resources are retrieved you can overwrite +collection and resource methods. The first is called on index action and the +second on all other actions. Let's suppose you want to add pagination to your +projects collection: + + class ProjectsController < InheritedResources::Base + protected + def collection + @projects ||= end_of_association_chain.paginate(:page => params[:page]) + end + end + +The end_of_association_chain returns your resource after nesting all associations +and scopes (more about this below). + +InheritedResources also introduces another method called begin_of_association_chain. +It's mostly used when you want to create resources based on the @current_user and +you have urls like "account/projects". In such cases, you have to do +@current_user.projects.find or @current_user.projects.build in your actions. + +You can deal with it just doing: + + class ProjectsController < InheritedResources::Base + protected + def begin_of_association_chain + @current_user + end + end + +== Overwriting actions + +Let's suppose that after destroying a project you want to redirect to your +root url instead of redirecting to projects url. You just have to do: + + class ProjectsController < InheritedResources::Base + def destroy + super do |format| + format.html { redirect_to root_url } + end + end + end + +You are opening your action and giving the parent action a new behavior. On +the other hand, I have to agree that calling super is not very readable. That's +why all methods have aliases. So this is equivalent: + + class ProjectsController < InheritedResources::Base + def destroy + destroy! do |format| + format.html { redirect_to root_url } + end + end + end + +Even more, since most of the times when you change a create, update or destroy +action is because you want to to change to where it redirects, a shortcut is +provided. So you can do: + + class ProjectsController < InheritedResources::Base + def destroy + destroy!{ root_url } + end + end + +If you simply want to change the flash message for a particular action, you can +pass the message to the parent action using the keys :notice and :alert (as you +would with flash): + + class ProjectsController < InheritedResources::Base + def create + create!(:notice => "Dude! Nice job creating that project.") + end + end + +You can still pass the block to change the redirect, as mentioned above: + + class ProjectsController < InheritedResources::Base + def create + create!(:notice => "Dude! Nice job creating that project.") { root_url } + end + end + +Now let's suppose that before create a project you have to do something special +but you don't want to create a before filter for it: + + class ProjectsController < InheritedResources::Base + def create + @project = Project.new(params[:project]) + @project.something_special! + create! + end + end + +Yes, that simple! The nice part is since you already set the instance variable +@project, it will not build a project again. + +Before we finish this topic, we should talk about one more thing: "success/failure +blocks". Let's suppose that when we update our project, in case of failure, we +want to redirect to the project url instead of re-rendering the edit template. + +Our first attempt to do this would be: + + class ProjectsController < InheritedResources::Base + def update + update! do |format| + unless @project.errors.empty? # failure + format.html { redirect_to project_url(@project) } + end + end + end + end + +Looks to verbose, right? We can actually do: + + class ProjectsController < InheritedResources::Base + def update + update! do |success, failure| + failure.html { redirect_to project_url(@project) } + end + end + end + +Much better! So explaining everything: when you give a block which expects one +argument it will be executed in both scenarios: success and failure. But If you +give a block that expects two arguments, the first will be executed only in +success scenarios and the second in failure scenarios. You keep everything +clean and organized inside the same action. + +== Smart redirects + +Although the syntax above is a nice shortcut, you won't need to do it frequently +because (since version 1.2) Inherited Resources has smart redirects. Redirects +in actions calculates depending on the existent controller methods. + +Redirects in create and update actions calculates in following order resource_url, +collection_url, parent_url (which we are going to see later), root_url. Redirect +in destroy action calculate in following order collection_url, parent_url, root_url. + +Example: + + class ButtonsConntroller < InheritedResources::Base + belongs_to :window + actions :all, :except => [:show, :index] + end + +This controller redirect to parent window after all CUD actions. + +== Success and failure scenarios on destroy + +The destroy action can also fail, this usually happens when you have a +before_destroy callback in your model which returns false. However, in +order to tell InheritedResources that it really failed, you need to add +errors to your model. So your before_destroy callback on the model should +be something like this: + + def before_destroy + if cant_be_destroyed? + errors.add(:base, "not allowed") + false + end + end + +== Belongs to + +Finally, our Projects are going to get some Tasks. Then you create a +TasksController and do: + + class TasksController < InheritedResources::Base + belongs_to :project + end + +belongs_to accepts several options to be able to configure the association. +For example, if you want urls like /projects/:project_title/tasks, you can +customize how InheritedResources find your projects: + + class TasksController < InheritedResources::Base + belongs_to :project, :finder => :find_by_title!, :param => :project_title + end + +It also accepts :route_name, :parent_class and :instance_name as options. +Check the lib/inherited_resources/class_methods.rb for more. + +== Nested belongs to + +Now, our Tasks get some Comments and you need to nest even deeper. Good +practices says that you should never nest more than two resources, but sometimes +you have to for security reasons. So this is an example of how you can do it: + + class CommentsController < InheritedResources::Base + nested_belongs_to :project, :task + end + +If you need to configure any of these belongs to, you can nest them using blocks: + + class CommentsController < InheritedResources::Base + belongs_to :project, :finder => :find_by_title!, :param => :project_title do + belongs_to :task + end + end + +Warning: calling several belongs_to is the same as nesting them: + + class CommentsConroller < InheritedResources::Base + belongs_to :project + belongs_to :task + end + +In other words, the code above is the same as calling nested_belongs_to. + +== Polymorphic belongs to + +We can go even further. Let's suppose our Projects can now have Files, Messages +and Tasks, and they are all commentable. In this case, the best solution is to +use polymorphism: + + class CommentsController < InheritedResources::Base + belongs_to :task, :file, :message, :polymorphic => true + # polymorphic_belongs_to :task, :file, :message + end + +You can even use it with nested resources: + + class CommentsController < InheritedResources::Base + belongs_to :project do + belongs_to :task, :file, :message, :polymorphic => true + end + end + +The url in such cases can be: + + /project/1/task/13/comments + /project/1/file/11/comments + /project/1/message/9/comments + +When using polymorphic associations, you get some free helpers: + + parent? #=> true + parent_type #=> :task + parent_class #=> Task + parent #=> @task + +Right now, Inherited Resources is limited and does not allow you +to have two polymorphic associations nested. + +== Optional belongs to + +Later you decide to create a view to show all comments, independent if they belong +to a task, file or message. You can reuse your polymorphic controller just doing: + + class CommentsController < InheritedResources::Base + belongs_to :task, :file, :message, :optional => true + # optional_belongs_to :task, :file, :message + end + +This will handle all those urls properly: + + /comment/1 + /tasks/2/comment/5 + /files/10/comment/3 + /messages/13/comment/11 + +This is treated as a special type of polymorphic associations, thus all helpers +are available. As you expect, when no parent is found, the helpers return: + + parent? #=> false + parent_type #=> nil + parent_class #=> nil + parent #=> nil + +== Singletons + +Now we are going to add manager to projects. We say that Manager is a singleton +resource because a Project has just one manager. You should declare it as +has_one (or resource) in your routes. + +To declare an association as singleton, you just have to give the :singleton +option. + + class ManagersController < InheritedResources::Base + belongs_to :project, :singleton => true + # singleton_belongs_to :project + end + +It will deal with everything again and hide the action :index from you. + +== Namespaced Controllers + +Namespaced controllers works out the box. + + class Forum::PostsController < InheritedResources::Base + end + +Inherited Resources prioritizes the default resource class for the namespaced controller in +this order: + + Forum::Post + ForumPost + Post + +== URL Helpers + +When you use InheritedResources it creates some URL helpers. +And they handle everything for you. :) + + # /posts/1/comments + resource_url # => /posts/1/comments/#{@comment.to_param} + resource_url(comment) # => /posts/1/comments/#{comment.to_param} + new_resource_url # => /posts/1/comments/new + edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit + edit_resource_url(comment) #=> /posts/1/comments/#{comment.to_param}/edit + collection_url # => /posts/1/comments + parent_url # => /posts/1 + + # /projects/1/tasks + resource_url # => /projects/1/tasks/#{@task.to_param} + resource_url(task) # => /projects/1/tasks/#{task.to_param} + new_resource_url # => /projects/1/tasks/new + edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit + edit_resource_url(task) # => /projects/1/tasks/#{task.to_param}/edit + collection_url # => /projects/1/tasks + parent_url # => /projects/1 + + # /users + resource_url # => /users/#{@user.to_param} + resource_url(user) # => /users/#{user.to_param} + new_resource_url # => /users/new + edit_resource_url # => /users/#{@user.to_param}/edit + edit_resource_url(user) # => /users/#{user.to_param}/edit + collection_url # => /users + parent_url # => / + +Those urls helpers also accepts a hash as options, just as in named routes. + + # /projects/1/tasks + collection_url(:page => 1, :limit => 10) #=> /projects/1/tasks?page=1&limit=10 + +In polymorphic cases, you can also give the parent as parameter to collection_url. + +Another nice thing is that those urls are not guessed during runtime. They are +all created when your application is loaded (except for polymorphic +associations, that relies on Rails polymorphic_url). + +== Custom actions + +Since version 1.2, Inherited Resources allows you to define custom actions in controller: + + class ButtonsController < InheritedResources::Base + custom_actions :resource => :delete, :collection => :search + end + +This code creates delete and search actions in controller (they behaves like show and +index actions accordingly). Also, it will produce delete_resource_{path,url} and +search_resources_{path,url} url helpers. + +== What about views? + +Sometimes just DRY the controllers is not enough, if you need to DRY up your views, +check this Wiki page: + +https://github.com/josevalim/inherited_resources/wiki/Views-Inheritance + +Notice that Rails 3.1 ships with view inheritance built-in. + +== Some DSL + +For those DSL lovers, InheritedResources won't leave you alone. You can overwrite +your success/failure blocks straight from your class binding. For it, you just +need to add a DSL module to your application controller: + + class ApplicationController < ActionController::Base + include InheritedResources::DSL + end + +And then you can rewrite the last example as: + + class ProjectsController < InheritedResources::Base + update! do |success, failure| + failure.html { redirect_to project_url(@project) } + end + end + +== Bugs and Feedback + +If you discover any bugs, please describe it in the issues tracker, including Rails and Inherited Resources versions. + +Questions are better handled on StackOverflow. + +Copyright (c) 2011 José Valim http://blog.plataformatec.com.br +See the attached MIT License. diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Rakefile b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Rakefile new file mode 100644 index 0000000..469e324 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/Rakefile @@ -0,0 +1,21 @@ +# encoding: UTF-8 + +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Run tests for InheritedResources.' +Rake::TestTask.new(:test) do |t| + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for InheritedResources.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'InheritedResources' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('MIT-LICENSE') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/app/controllers/inherited_resources/base.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/app/controllers/inherited_resources/base.rb new file mode 100644 index 0000000..9fafb7e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/app/controllers/inherited_resources/base.rb @@ -0,0 +1,43 @@ +module InheritedResources + # = Base + # + # This is the base class that holds all actions. If you see the code for each + # action, they are quite similar to Rails default scaffold. + # + # To change your base behavior, you can overwrite your actions and call super, + # call default class method, call <actions class method + # or overwrite some helpers in the base_helpers.rb file. + # + class Base < ::ApplicationController + # Overwrite inherit_resources to add specific InheritedResources behavior. + def self.inherit_resources(base) + base.class_eval do + include InheritedResources::Actions + include InheritedResources::BaseHelpers + extend InheritedResources::ClassMethods + extend InheritedResources::UrlHelpers + + # Add at least :html mime type + respond_to :html if self.mimes_for_respond_to.empty? + self.responder = InheritedResources::Responder + + helper_method :resource, :collection, :resource_class, :association_chain, + :resource_instance_name, :resource_collection_name, + :resource_url, :resource_path, + :collection_url, :collection_path, + :new_resource_url, :new_resource_path, + :edit_resource_url, :edit_resource_path, + :parent_url, :parent_path, + :smart_resource_url, :smart_collection_url + + self.class_attribute :resource_class, :instance_writer => false unless self.respond_to? :resource_class + self.class_attribute :parents_symbols, :resources_configuration, :instance_writer => false + + protected :resource_class, :parents_symbols, :resources_configuration, + :resource_class?, :parents_symbols?, :resources_configuration? + end + end + + inherit_resources(self) + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/inherited_resources.gemspec b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/inherited_resources.gemspec new file mode 100644 index 0000000..a96d076 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/inherited_resources.gemspec @@ -0,0 +1,24 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "inherited_resources/version" + +Gem::Specification.new do |s| + s.name = "inherited_resources" + s.version = InheritedResources::VERSION.dup + s.platform = Gem::Platform::RUBY + s.summary = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important." + s.email = "developers@plataformatec.com.br" + s.homepage = "http://github.com/josevalim/inherited_resources" + s.description = "Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important." + s.authors = ['José Valim'] + + s.rubyforge_project = "inherited_resources" + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] + + s.add_dependency("responders", "~> 0.6.0") + s.add_dependency("has_scope", "~> 0.5.0") +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/USAGE b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/USAGE new file mode 100644 index 0000000..2543041 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/USAGE @@ -0,0 +1,10 @@ +Description: + Stubs out a scaffolded controller and its views using InheritedResources. + Pass the model name, either CamelCased or under_scored. The controller + name is retrieved as a pluralized version of the model name. + + To create a controller within a module, specify the model name as a + path like 'parent_module/controller_name'. + + This generates a controller class in app/controllers and invokes helper, + template engine and test framework generators. diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/inherited_resources_controller_generator.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/inherited_resources_controller_generator.rb new file mode 100644 index 0000000..89ffca6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/inherited_resources_controller_generator.rb @@ -0,0 +1,11 @@ +require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator' + +module Rails + module Generators + class InheritedResourcesControllerGenerator < ScaffoldControllerGenerator + def self.source_root + @source_root ||= File.expand_path("templates", File.dirname(__FILE__)) + end + end + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/templates/controller.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/templates/controller.rb new file mode 100644 index 0000000..a6edba4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/generators/rails/templates/controller.rb @@ -0,0 +1,5 @@ +class <%= controller_class_name %>Controller < InheritedResources::Base +<% if options[:singleton] -%> + defaults :singleton => true +<% end -%> +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources.rb new file mode 100644 index 0000000..96e4288 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources.rb @@ -0,0 +1,44 @@ +require 'rails/engine' +require 'responders' +require 'inherited_resources/blank_slate' +require 'inherited_resources/responder' + +module InheritedResources + ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:ACTIONS) + + autoload :Actions, 'inherited_resources/actions' + autoload :BaseHelpers, 'inherited_resources/base_helpers' + autoload :ShallowHelpers, 'inherited_resources/shallow_helpers' + autoload :BelongsToHelpers, 'inherited_resources/belongs_to_helpers' + autoload :ClassMethods, 'inherited_resources/class_methods' + autoload :DSL, 'inherited_resources/dsl' + autoload :PolymorphicHelpers, 'inherited_resources/polymorphic_helpers' + autoload :SingletonHelpers, 'inherited_resources/singleton_helpers' + autoload :UrlHelpers, 'inherited_resources/url_helpers' + autoload :VERSION, 'inherited_resources/version' + + # Change the flash keys used by FlashResponder. + def self.flash_keys=(array) + Responders::FlashResponder.flash_keys = array + end + + class Railtie < ::Rails::Engine + config.inherited_resources = InheritedResources + if config.respond_to?(:app_generators) + config.app_generators.scaffold_controller = :inherited_resources_controller + else + config.generators.scaffold_controller = :inherited_resources_controller + end + end +end + +class ActionController::Base + # If you cannot inherit from InheritedResources::Base you can call + # inherit_resource in your controller to have all the required modules and + # funcionality included. + def self.inherit_resources + InheritedResources::Base.inherit_resources(self) + initialize_resources_class_accessors! + create_resources_url_helpers! + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/actions.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/actions.rb new file mode 100644 index 0000000..22332f5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/actions.rb @@ -0,0 +1,67 @@ +module InheritedResources + # Holds all default actions for InheritedResouces. + module Actions + + # GET /resources + def index(options={}, &block) + respond_with(*(with_chain(collection) << options), &block) + end + alias :index! :index + + # GET /resources/1 + def show(options={}, &block) + respond_with(*(with_chain(resource) << options), &block) + end + alias :show! :show + + # GET /resources/new + def new(options={}, &block) + respond_with(*(with_chain(build_resource) << options), &block) + end + alias :new! :new + + # GET /resources/1/edit + def edit(options={}, &block) + respond_with(*(with_chain(resource) << options), &block) + end + alias :edit! :edit + + # POST /resources + def create(options={}, &block) + object = build_resource + + if create_resource(object) + options[:location] ||= smart_resource_url + end + + respond_with_dual_blocks(object, options, &block) + end + alias :create! :create + + # PUT /resources/1 + def update(options={}, &block) + object = resource + + if update_resource(object, resource_params) + options[:location] ||= smart_resource_url + end + + respond_with_dual_blocks(object, options, &block) + end + alias :update! :update + + # DELETE /resources/1 + def destroy(options={}, &block) + object = resource + options[:location] ||= smart_collection_url + + destroy_resource(object) + respond_with_dual_blocks(object, options, &block) + end + alias :destroy! :destroy + + # Make aliases protected + protected :index!, :show!, :new!, :create!, :edit!, :update!, :destroy! + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/base_helpers.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/base_helpers.rb new file mode 100644 index 0000000..d0db37e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/base_helpers.rb @@ -0,0 +1,319 @@ +# Whenever base is required load the dumb responder since it's used inside actions. +require 'inherited_resources/blank_slate' + +module InheritedResources + # Base helpers for InheritedResource work. Some methods here can be overwriten + # and you will need to do that to customize your controllers from time to time. + # + module BaseHelpers + + protected + + # This is how the collection is loaded. + # + # You might want to overwrite this method if you want to add pagination + # for example. When you do that, don't forget to cache the result in an + # instance_variable: + # + # def collection + # @projects ||= end_of_association_chain.paginate(params[:page]).all + # end + # + def collection + get_collection_ivar || begin + c = end_of_association_chain + set_collection_ivar(c.respond_to?(:scoped) ? c.scoped : c.all) + end + end + + # This is how the resource is loaded. + # + # You might want to overwrite this method when you are using permalink. + # When you do that, don't forget to cache the result in an + # instance_variable: + # + # def resource + # @project ||= end_of_association_chain.find_by_permalink!(params[:id]) + # end + # + # You also might want to add the exclamation mark at the end of the method + # because it will raise a 404 if nothing can be found. Otherwise it will + # probably render a 500 error message. + # + def resource + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_find, params[:id])) + end + + # This method is responsable for building the object on :new and :create + # methods. If you overwrite it, don't forget to cache the result in an + # instance variable. + # + def build_resource + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, *resource_params)) + end + + # Responsible for saving the resource on :create method. Overwriting this + # allow you to control the way resource is saved. Let's say you have a + # PassworsController who is responsible for finding an user by email and + # sent password instructions for him. Instead of overwriting the entire + # :create method, you could do something: + # + # def create_resource(object) + # object.send_instructions_by_email + # end + # + def create_resource(object) + object.save + end + + # Responsible for updating the resource in :update method. This allow you + # to handle how the resource is gona be updated, let's say in a different + # way then the usual :update_attributes: + # + # def update_resource(object, attributes) + # object.reset_password!(attributes) + # end + # + def update_resource(object, attributes) + object.update_attributes(*attributes) + end + + # Handle the :destroy method for the resource. Overwrite it to call your + # own method for destroing the resource, as: + # + # def destroy_resource(object) + # object.cancel + # end + # + def destroy_resource(object) + object.destroy + end + + # This class allows you to set a instance variable to begin your + # association chain. For example, usually your projects belongs to users + # and that means that they belong to the current logged in user. So you + # could do this: + # + # def begin_of_association_chain + # @current_user + # end + # + # So every time we instantiate a project, we will do: + # + # @current_user.projects.build(params[:project]) + # @current_user.projects.find(params[:id]) + # + # The variable set in begin_of_association_chain is not sent when building + # urls, so this is never going to happen when calling resource_url: + # + # project_url(@current_user, @project) + # + # If the user actually scopes the url, you should use belongs_to method + # and declare that projects belong to user. + # + def begin_of_association_chain + nil + end + + # Returns if the controller has a parent. When only base helpers are loaded, + # it's always false and should not be overwriten. + # + def parent? + false + end + + # Returns the association chain, with all parents (does not include the + # current resource). + # + def association_chain + @association_chain ||= + symbols_for_association_chain.inject([begin_of_association_chain]) do |chain, symbol| + chain << evaluate_parent(symbol, resources_configuration[symbol], chain.last) + end.compact.freeze + end + + # Overwrite this method to provide other interpolation options when + # the flash message is going to be set. + # + # def interpolation_options + # { } + # end + + private + + # Adds the given object to association chain. + def with_chain(object) + association_chain + [ object ] + end + + # Fast accessor to resource_collection_name + # + def resource_collection_name #:nodoc: + self.resources_configuration[:self][:collection_name] + end + + # Fast accessor to resource_instance_name + # + def resource_instance_name #:nodoc: + self.resources_configuration[:self][:instance_name] + end + + def resource_request_name + self.resources_configuration[:self][:request_name] + end + + # This methods gets your begin_of_association_chain, join it with your + # parents chain and returns the scoped association. + # + def end_of_association_chain #:nodoc: + if chain = association_chain.last + if method_for_association_chain + apply_scopes_if_available(chain.send(method_for_association_chain)) + else + # This only happens when we specify begin_of_association_chain in + # a singletion controller without parents. In this case, the chain + # is exactly the begin_of_association_chain which is already an + # instance and then not scopable. + chain + end + else + apply_scopes_if_available(resource_class) + end + end + + # Returns the appropriated method to build the resource. + # + def method_for_build #:nodoc: + (begin_of_association_chain || parent?) ? method_for_association_build : :new + end + + # Returns the name of the method used for build the resource in cases + # where we have a parent. This is overwritten in singleton scenarios. + # + def method_for_association_build + :build + end + + # Returns the name of the method to be called, before returning the end + # of the association chain. This is overwriten by singleton cases + # where no method for association chain is called. + # + def method_for_association_chain #:nodoc: + resource_collection_name + end + + # Returns finder method for instantiate resource by params[:id] + def method_for_find + resources_configuration[:self][:finder] || :find + end + + # Get resource ivar based on the current resource controller. + # + def get_resource_ivar #:nodoc: + instance_variable_get("@#{resource_instance_name}") + end + + # Set resource ivar based on the current resource controller. + # + def set_resource_ivar(resource) #:nodoc: + instance_variable_set("@#{resource_instance_name}", resource) + end + + # Get collection ivar based on the current resource controller. + # + def get_collection_ivar #:nodoc: + instance_variable_get("@#{resource_collection_name}") + end + + # Set collection ivar based on the current resource controller. + # + def set_collection_ivar(collection) #:nodoc: + instance_variable_set("@#{resource_collection_name}", collection) + end + + # Used to allow to specify success and failure within just one block: + # + # def create + # create! do |success, failure| + # failure.html { redirect_to root_url } + # end + # end + # + # It also calculates the response url in case a block without arity is + # given and returns it. Otherwise returns nil. + # + def respond_with_dual_blocks(object, options, &block) #:nodoc: + args = (with_chain(object) << options) + + case block.try(:arity) + when 2 + respond_with(*args) do |responder| + blank_slate = InheritedResources::BlankSlate.new + if object.errors.empty? + block.call(responder, blank_slate) + else + block.call(blank_slate, responder) + end + end + when 1 + respond_with(*args, &block) + else + options[:location] = block.call if block + respond_with(*args) + end + end + + # Hook to apply scopes. By default returns only the target_object given. + # It's extend by HasScopeHelpers. + # + def apply_scopes_if_available(target_object) #:nodoc: + respond_to?(:apply_scopes) ? apply_scopes(target_object) : target_object + end + + # Symbols chain in base helpers return nothing. This is later overwriten + # by belongs_to and can be complex in polymorphic cases. + # + def symbols_for_association_chain #:nodoc: + [] + end + + # URL to redirect to when redirect implies resource url. + def smart_resource_url + url = nil + if respond_to? :show + url = resource_url rescue nil + end + url ||= smart_collection_url + end + + # URL to redirect to when redirect implies collection url. + def smart_collection_url + url = nil + if respond_to? :index + url ||= collection_url rescue nil + end + if respond_to? :parent + url ||= parent_url rescue nil + end + url ||= root_url rescue nil + end + + # extract attributes from params + def resource_params + rparams = [params[resource_request_name] || params[resource_instance_name] || {}] + rparams << as_role if role_given? + rparams + end + + # checking if role given + def role_given? + self.resources_configuration[:self][:role].present? + end + + # getting role for mass-asignment + def as_role + { :as => self.resources_configuration[:self][:role] } + end + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/belongs_to_helpers.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/belongs_to_helpers.rb new file mode 100644 index 0000000..c120038 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/belongs_to_helpers.rb @@ -0,0 +1,97 @@ +module InheritedResources + + # = belongs_to + # + # Let's suppose that we have some tasks that belongs to projects. To specify + # this assoication in your controllers, just do: + # + # class TasksController < InheritedResources::Base + # belongs_to :project + # end + # + # belongs_to accepts several options to be able to configure the association. + # For example, if you want urls like /projects/:project_title/tasks, you + # can customize how InheritedResources find your projects: + # + # class TasksController < InheritedResources::Base + # belongs_to :project, :finder => :find_by_title!, :param => :project_title + # end + # + # It also accepts :route_name, :parent_class and :instance_name as options. + # Check the lib/inherited_resources/class_methods.rb for more. + # + # = nested_belongs_to + # + # Now, our Tasks get some Comments and you need to nest even deeper. Good + # practices says that you should never nest more than two resources, but sometimes + # you have to for security reasons. So this is an example of how you can do it: + # + # class CommentsController < InheritedResources::Base + # nested_belongs_to :project, :task + # end + # + # If you need to configure any of these belongs to, you can nested them using blocks: + # + # class CommentsController < InheritedResources::Base + # belongs_to :project, :finder => :find_by_title!, :param => :project_title do + # belongs_to :task + # end + # end + # + # Warning: calling several belongs_to is the same as nesting them: + # + # class CommentsController < InheritedResources::Base + # belongs_to :project + # belongs_to :task + # end + # + # In other words, the code above is the same as calling nested_belongs_to. + # + module BelongsToHelpers + + protected + + # Parent is always true when belongs_to is called. + # + def parent? + true + end + + def parent + @parent ||= association_chain[-1] + end + + def parent_type + parent.class.name.underscore.to_sym + end + + private + + # Evaluate the parent given. This is used to nest parents in the + # association chain. + # + def evaluate_parent(parent_symbol, parent_config, chain = nil) #:nodoc: + instantiated_object = instance_variable_get("@#{parent_config[:instance_name]}") + return instantiated_object if instantiated_object + + parent = if chain + chain.send(parent_config[:collection_name]) + else + parent_config[:parent_class] + end + + parent = parent.send(parent_config[:finder], params[parent_config[:param]]) + + instance_variable_set("@#{parent_config[:instance_name]}", parent) + end + + # Maps parents_symbols to build association chain. In this case, it + # simply return the parent_symbols, however on polymorphic belongs to, + # it has some customization. + # + def symbols_for_association_chain #:nodoc: + parents_symbols + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/blank_slate.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/blank_slate.rb new file mode 100644 index 0000000..cf718a3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/blank_slate.rb @@ -0,0 +1,12 @@ +module InheritedResources + # An object from BlankSlate simply discards all messages sent to it. + class BlankSlate + instance_methods.each do |m| + undef_method m unless m =~ /^(__|object_id)/ + end + + def method_missing(*args) + nil + end + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/class_methods.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/class_methods.rb new file mode 100644 index 0000000..fc98e4d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/class_methods.rb @@ -0,0 +1,374 @@ +module InheritedResources + module ClassMethods + + protected + + # Used to overwrite the default assumptions InheritedResources do. Whenever + # this method is called, it should be on the top of your controller, since + # almost other methods depends on the values given to <>defaults. + # + # == Options + # + # * :resource_class - The resource class which by default is guessed + # by the controller name. Defaults to Project in + # ProjectsController. + # + # * :collection_name - The name of the collection instance variable which + # is set on the index action. Defaults to :projects in + # ProjectsController. + # + # * :instance_name - The name of the singular instance variable which + # is set on all actions besides index action. Defaults to + # :project in ProjectsController. + # + # * :route_collection_name - The name of the collection route. Defaults to :collection_name. + # + # * :route_instance_name - The name of the singular route. Defaults to :instance_name. + # + # * :route_prefix - The route prefix which is automically set in namespaced + # controllers. Default to :admin on Admin::ProjectsController. + # + # * :singleton - Tells if this controller is singleton or not. + # + # * :finder - Specifies which method should be called to instantiate the resource. + # + # defaults :project, :finder => :find_by_slug + # + def defaults(options) + raise ArgumentError, 'Class method :defaults expects a hash of options.' unless options.is_a? Hash + + options.symbolize_keys! + options.assert_valid_keys(:resource_class, :collection_name, :instance_name, + :class_name, :route_prefix, :route_collection_name, + :route_instance_name, :singleton, :finder) + + self.resource_class = options[:resource_class] if options.key?(:resource_class) + self.resource_class = options[:class_name].constantize if options.key?(:class_name) + + acts_as_singleton! if options.delete(:singleton) + + config = self.resources_configuration[:self] + config[:route_prefix] = options.delete(:route_prefix) if options.key?(:route_prefix) + + if options.key?(:resource_class) or options.key?(:class_name) + config[:request_name] = self.resource_class.to_s.underscore.gsub('/', '_') + options.delete(:resource_class) and options.delete(:class_name) + end + + options.each do |key, value| + config[key] = value.to_sym + end + + create_resources_url_helpers! + end + + # Defines wich actions to keep from the inherited controller. + # Syntax is borrowed from resource_controller. + # + # actions :index, :show, :edit + # actions :all, :except => :index + # + def actions(*actions_to_keep) + raise ArgumentError, 'Wrong number of arguments. You have to provide which actions you want to keep.' if actions_to_keep.empty? + + options = actions_to_keep.extract_options! + actions_to_remove = Array(options[:except]) + actions_to_remove += ACTIONS - actions_to_keep.map { |a| a.to_sym } unless actions_to_keep.first == :all + actions_to_remove.map! { |a| a.to_sym }.uniq! + (instance_methods.map { |m| m.to_sym } & actions_to_remove).each do |action| + undef_method action, "#{action}!" + end + end + + # Defines that this controller belongs to another resource. + # + # belongs_to :projects + # + # == Options + # + # * :parent_class - Allows you to specify what is the parent class. + # + # belongs_to :project, :parent_class => AdminProject + # + # * :class_name - Also allows you to specify the parent class, but you should + # give a string. Added for ActiveRecord belongs to compatibility. + # + # * :instance_name - The instance variable name. By default is the name of the association. + # + # belongs_to :project, :instance_name => :my_project + # + # * :finder - Specifies which method should be called to instantiate the parent. + # + # belongs_to :project, :finder => :find_by_title! + # + # This will make your projects be instantiated as: + # + # Project.find_by_title!(params[:project_id]) + # + # Instead of: + # + # Project.find(params[:project_id]) + # + # * :param - Allows you to specify params key to retrieve the id. + # Default is :association_id, which in this case is :project_id. + # + # * :route_name - Allows you to specify what is the route name in your url + # helper. By default is association name. + # + # * :collection_name - Tell how to retrieve the next collection. Let's + # suppose you have Tasks which belongs to Projects + # which belongs to companies. This will do somewhere + # down the road: + # + # @company.projects + # + # But if you want to retrieve instead: + # + # @company.admin_projects + # + # You supply the collection name. + # + # * :polymorphic - Tell the association is polymorphic. + # + # * :singleton - Tell it's a singleton association. + # + # * :optional - Tell the association is optional (it's a special + # type of polymorphic association) + # + def belongs_to(*symbols, &block) + options = symbols.extract_options! + + options.symbolize_keys! + options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param, + :finder, :route_name, :collection_name, :singleton, + :polymorphic, :optional, :shallow) + + optional = options.delete(:optional) + shallow = options.delete(:shallow) + singleton = options.delete(:singleton) + polymorphic = options.delete(:polymorphic) + finder = options.delete(:finder) + + include BelongsToHelpers if self.parents_symbols.empty? + + acts_as_singleton! if singleton + acts_as_polymorphic! if polymorphic || optional + acts_as_shallow! if shallow + + raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty? + raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty? + + symbols.each do |symbol| + symbol = symbol.to_sym + + if polymorphic || optional + self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic) + self.resources_configuration[:polymorphic][:symbols] << symbol + self.resources_configuration[:polymorphic][:optional] ||= optional + else + self.parents_symbols << symbol + end + + self.resources_configuration[:self][:shallow] = true if shallow + + config = self.resources_configuration[symbol] = {} + + config[:parent_class] = options.delete(:parent_class) || begin + class_name = (options.delete(:class_name) || symbol).to_s.pluralize.classify + class_name.constantize + rescue NameError => e + raise unless e.message.include?(class_name) + nil + end + + config[:collection_name] = options.delete(:collection_name) || symbol.to_s.pluralize.to_sym + config[:instance_name] = options.delete(:instance_name) || symbol + config[:param] = options.delete(:param) || :"#{symbol}_id" + config[:route_name] = options.delete(:route_name) || symbol + config[:finder] = finder || :find + end + + if block_given? + class_eval(&block) + else + create_resources_url_helpers! + end + helper_method :parent, :parent? + end + alias :nested_belongs_to :belongs_to + + # A quick method to declare polymorphic belongs to. + # + def polymorphic_belongs_to(*symbols, &block) + options = symbols.extract_options! + options.merge!(:polymorphic => true) + belongs_to(*symbols << options, &block) + end + + # A quick method to declare singleton belongs to. + # + def singleton_belongs_to(*symbols, &block) + options = symbols.extract_options! + options.merge!(:singleton => true) + belongs_to(*symbols << options, &block) + end + + # A quick method to declare optional belongs to. + # + def optional_belongs_to(*symbols, &block) + options = symbols.extract_options! + options.merge!(:optional => true) + belongs_to(*symbols << options, &block) + end + + # Defines custom restful actions by resource or collection basis. + # + # custom_actions :resource => [:delete, :transit], :collection => :search + # + # == Options + # + # * :resource - Allows you to specify resource actions. + # custom_actions :resource => :delete + # This macro creates 'delete' method in controller and defines + # delete_reource_{path,url} helpers. The body of generated 'delete' + # method is same as 'show' method. So you can override it if need + # + # * :collection - Allows you to specify collection actions. + # custom_actions :collection => :search + # This macro creates 'search' method in controller and defines + # search_reources_{path,url} helpers. The body of generated 'search' + # method is same as 'index' method. So you can override it if need + # + def custom_actions(options) + self.resources_configuration[:self][:custom_actions] = options + options.each do | resource_or_collection, actions | + [*actions].each do | action | + create_custom_action(resource_or_collection, action) + end + end + create_resources_url_helpers! + [*options[:resource]].each do | action | + helper_method "#{action}_resource_path", "#{action}_resource_url" + end + [*options[:collection]].each do | action | + helper_method "#{action}_resources_path", "#{action}_resources_url" + end + end + + # Defines the role to use when creating or updating resource. + # Makes sense when using rails 3.1 mass assignment conventions + def with_role(role) + self.resources_configuration[:self][:role] = role.try(:to_sym) + end + + private + + def acts_as_singleton! #:nodoc: + unless self.resources_configuration[:self][:singleton] + self.resources_configuration[:self][:singleton] = true + include SingletonHelpers + actions :all, :except => :index + end + end + + def acts_as_polymorphic! #:nodoc: + unless self.parents_symbols.include?(:polymorphic) + include PolymorphicHelpers + helper_method :parent_type, :parent_class + end + end + + def acts_as_shallow! #:nodoc: + include BelongsToHelpers + include ShallowHelpers + end + + # Initialize resources class accessors and set their default values. + # + def initialize_resources_class_accessors! #:nodoc: + # First priority is the namespaced model, e.g. User::Group + self.resource_class ||= begin + namespaced_class = self.name.sub(/Controller/, '').singularize + namespaced_class.constantize + rescue NameError + nil + end + + # Second priority is the top namespace model, e.g. EngineName::Article for EngineName::Admin::ArticlesController + self.resource_class ||= begin + namespaced_classes = self.name.sub(/Controller/, '').split('::') + namespaced_class = [namespaced_classes.first, namespaced_classes.last].join('::').singularize + namespaced_class.constantize + rescue NameError + nil + end + + # Third priority the camelcased c, i.e. UserGroup + self.resource_class ||= begin + camelcased_class = self.name.sub(/Controller/, '').gsub('::', '').singularize + camelcased_class.constantize + rescue NameError + nil + end + + # Otherwise use the Group class, or fail + self.resource_class ||= begin + class_name = self.controller_name.classify + class_name.constantize + rescue NameError => e + raise unless e.message.include?(class_name) + nil + end + + self.parents_symbols = self.parents_symbols.try(:dup) || [] + + # Initialize resources configuration hash + self.resources_configuration = self.resources_configuration.try(:dup) || {} + self.resources_configuration.each do |key, value| + next unless value.is_a?(Hash) || value.is_a?(Array) + self.resources_configuration[key] = value.dup + end + + config = (self.resources_configuration[:self] ||= {}) + config[:collection_name] = self.controller_name.to_sym + config[:instance_name] = self.controller_name.singularize.to_sym + + config[:route_collection_name] = config[:collection_name] + config[:route_instance_name] = config[:instance_name] + + # Deal with namespaced controllers + namespaces = self.controller_path.split('/')[0..-2] + config[:route_prefix] = namespaces.join('_') unless namespaces.empty? + + # Deal with default request parameters in namespaced controllers, e.g. + # Forum::Thread#create will properly pick up the request parameter + # which will be forum_thread, and not thread + # Additionally make this work orthogonally with instance_name + config[:request_name] = self.resource_class.to_s.underscore.gsub('/', '_') + + # Initialize polymorphic, singleton, scopes and belongs_to parameters + polymorphic = self.resources_configuration[:polymorphic] || { :symbols => [], :optional => false } + polymorphic[:symbols] = polymorphic[:symbols].dup + self.resources_configuration[:polymorphic] = polymorphic + end + + def create_custom_action(resource_or_collection, action) + class_eval <<-CUSTOM_ACTION, __FILE__, __LINE__ + def #{action}(options={}, &block) + respond_with(*(with_chain(#{resource_or_collection}) << options), &block) + end + alias :#{action}! :#{action} + protected :#{action}! + CUSTOM_ACTION + end + + # Hook called on inheritance. + # + def inherited(base) #:nodoc: + super(base) + base.send :initialize_resources_class_accessors! + base.send :create_resources_url_helpers! + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/dsl.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/dsl.rb new file mode 100644 index 0000000..2b3a57d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/dsl.rb @@ -0,0 +1,26 @@ +module InheritedResources + # Allows controllers to write actions using a class method DSL. + # + # class MyController < InheritedResources::Base + # create! do |success, failure| + # success.html { render :text => "It works!" } + # end + # end + # + module DSL + def self.included(base) + ACTIONS.each do |action| + base.class_eval <<-WRITTER + def self.#{action}!(options={}, &block) + define_method :__#{action}, &block + class_eval <<-ACTION + def #{action} + super(\#{options.inspect}, &method(:__#{action})) + end + ACTION + end + WRITTER + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/polymorphic_helpers.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/polymorphic_helpers.rb new file mode 100644 index 0000000..a04b339 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/polymorphic_helpers.rb @@ -0,0 +1,155 @@ +module InheritedResources + + # = polymorphic associations + # + # In some cases you have a resource that belongs to two different resources + # but not at the same time. For example, let's suppose you have File, Message + # and Task as resources and they are all commentable. + # + # Polymorphic associations allows you to create just one controller that will + # deal with each case. + # + # class Comment < InheritedResources::Base + # belongs_to :file, :message, :task, :polymorphic => true + # end + # + # Your routes should be something like: + # + # m.resources :files, :has_many => :comments #=> /files/13/comments + # m.resources :tasks, :has_many => :comments #=> /tasks/17/comments + # m.resources :messages, :has_many => :comments #=> /messages/11/comments + # + # When using polymorphic associations, you get some free helpers: + # + # parent? #=> true + # parent_type #=> :task + # parent_class #=> Task + # parent #=> @task + # + # This polymorphic controllers thing is a great idea by James Golick and he + # built it in resource_controller. Here is just a re-implementation. + # + # = optional polymorphic associations + # + # Let's take another break from ProjectsController. Let's suppose we are + # building a store, which sell products. + # + # On the website, we can show all products, but also products scoped to + # categories, brands, users. In this case case, the association is optional, and + # we deal with it in the following way: + # + # class ProductsController < InheritedResources::Base + # belongs_to :category, :brand, :user, :polymorphic => true, :optional => true + # end + # + # This will handle all those urls properly: + # + # /products/1 + # /categories/2/products/5 + # /brands/10/products/3 + # /user/13/products/11 + # + # = nested polymorphic associations + # + # You can have polymorphic associations with nested resources. Let's suppose + # that our File, Task and Message resources in the previous example belongs to + # a project. + # + # This way we can have: + # + # class CommentsController < InheritedResources::Base + # belongs_to :project { + # belongs_to :file, :message, :task, :polymorphic => true + # } + # end + # + # Or: + # + # class CommentsController < InheritedResources::Base + # nested_belongs_to :project + # nested_belongs_to :file, :message, :task, :polymorphic => true + # end + # + # Choose the syntax that makes more sense to you. :) + # + # Finally your routes should be something like: + # + # map.resources :projects do |m| + # m.resources :files, :has_many => :comments #=> /projects/1/files/13/comments + # m.resources :tasks, :has_many => :comments #=> /projects/1/tasks/17/comments + # m.resources :messages, :has_many => :comments #=> /projects/1/messages/11/comments + # end + # + # The helpers work in the same way as above. + # + module PolymorphicHelpers + + protected + + # Returns the parent type. A Comments class can have :task, :file, :note + # as parent types. + # + def parent_type + @parent_type + end + + def parent_class + parent.class if @parent_type + end + + # Returns the parent object. They are also available with the instance + # variable name: @task, @file, @note... + # + def parent + instance_variable_get("@#{@parent_type}") if @parent_type + end + + # If the polymorphic association is optional, we might not have a parent. + # + def parent? + if resources_configuration[:polymorphic][:optional] + parents_symbols.size > 1 || !@parent_type.nil? + else + true + end + end + + private + + # Maps parents_symbols to build association chain. + # + # If the parents_symbols find :polymorphic, it goes through the + # params keys to see which polymorphic parent matches the given params. + # + # When optional is given, it does not raise errors if the polymorphic + # params are missing. + # + def symbols_for_association_chain #:nodoc: + polymorphic_config = resources_configuration[:polymorphic] + parents_symbols.map do |symbol| + if symbol == :polymorphic + params_keys = params.keys + + keys = polymorphic_config[:symbols].map do |poly| + params_keys.include?(resources_configuration[poly][:param].to_s) ? poly : nil + end.compact + + if keys.empty? + raise ScriptError, "Could not find param for polymorphic association. The request" << + "parameters are #{params.keys.inspect} and the polymorphic " << + "associations are #{polymorphic_config[:symbols].inspect}." unless polymorphic_config[:optional] + + nil + else + @parent_type = keys[-1].to_sym + @parent_types = keys.map(&:to_sym) + end + else + symbol + end + end.flatten.compact + end + + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/responder.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/responder.rb new file mode 100644 index 0000000..596214e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/responder.rb @@ -0,0 +1,6 @@ +module InheritedResources + class Responder < ActionController::Responder + include Responders::FlashResponder + include Responders::HttpCacheResponder + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/shallow_helpers.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/shallow_helpers.rb new file mode 100644 index 0000000..ff993eb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/shallow_helpers.rb @@ -0,0 +1,43 @@ +module InheritedResources + # Shallow provides a functionality that goes on pair with Rails' shallow. + # It is very similar to "optional" but it actually finds all the parents + # resources instead of leaving them blank. Consider the following example: + # + # belongs_to :post, :shallow => true do + # belongs_to :comment + # end + # + # When accessed as /comments/1, Inherited Resources will automatically get + # the post resource so both objects are actually accessible through the views. + # + # However, when using optional, Inherited Resources wouldn't actually bother + # with finding the parent object. + module ShallowHelpers + private + + def symbols_for_association_chain #:nodoc: + parent_symbols = parents_symbols.dup + instance = nil + + if id = params[:id] + finder_method = resources_configuration[:self][:finder] || :find + instance = self.resource_class.send(finder_method, id) + elsif parents_symbols.size > 1 + config = resources_configuration[parent_symbols.pop] + finder_method = config[:finder] || :find + instance = config[:parent_class].send(finder_method, params[config[:param]]) + end + + load_parents(instance, parent_symbols) if instance + parents_symbols + end + + def load_parents(instance, parent_symbols) + parent_symbols.reverse.each do |parent| + instance = instance.send(parent) + config = resources_configuration[parent] + params[config[:param]] = instance.to_param + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/singleton_helpers.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/singleton_helpers.rb new file mode 100644 index 0000000..9395517 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/singleton_helpers.rb @@ -0,0 +1,95 @@ +module InheritedResources + + # = singleton + # + # Singletons are usually used in associations which are related through has_one + # and belongs_to. You declare those associations like this: + # + # class ManagersController < InheritedResources::Base + # belongs_to :project, :singleton => true + # end + # + # But in some cases, like an AccountsController, you have a singleton object + # that is not necessarily associated with another: + # + # class AccountsController < InheritedResources::Base + # defaults :singleton => true + # end + # + # Besides that, you should overwrite the methods :resource and :build_resource + # to make it work properly: + # + # class AccountsController < InheritedResources::Base + # defaults :singleton => true + # + # protected + # def resource + # @current_user.account + # end + # + # def build_resource(attributes = {}) + # Account.new(attributes) + # end + # end + # + # When you have a singleton controller, the action index is removed. + # + module SingletonHelpers + + protected + + # Singleton methods does not deal with collections. + # + def collection + nil + end + + # Overwrites how singleton deals with resource. + # + # If you are going to overwrite it, you should notice that the + # end_of_association_chain here is not the same as in default belongs_to. + # + # class TasksController < InheritedResources::Base + # belongs_to :project + # end + # + # In this case, the association chain would be: + # + # Project.find(params[:project_id]).tasks + # + # So you would just have to call find(:all) at the end of association + # chain. And this is what happened. + # + # In singleton controllers: + # + # class ManagersController < InheritedResources::Base + # belongs_to :project, :singleton => true + # end + # + # The association chain will be: + # + # Project.find(params[:project_id]) + # + # So we have to call manager on it, not find. + # + def resource + get_resource_ivar || set_resource_ivar(end_of_association_chain.send(resource_instance_name)) + end + + private + + # Returns the appropriated method to build the resource. + # + def method_for_association_build #:nodoc: + :"build_#{resource_instance_name}" + end + + # Sets the method_for_association_chain to nil. See resource + # above for more information. + # + def method_for_association_chain #:nodoc: + nil + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/url_helpers.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/url_helpers.rb new file mode 100644 index 0000000..c4b132f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/url_helpers.rb @@ -0,0 +1,228 @@ +module InheritedResources + # = URLHelpers + # + # When you use InheritedResources it creates some UrlHelpers for you. + # And they handle everything for you. + # + # # /posts/1/comments + # resource_url # => /posts/1/comments/#{@comment.to_param} + # resource_url(comment) # => /posts/1/comments/#{comment.to_param} + # new_resource_url # => /posts/1/comments/new + # edit_resource_url # => /posts/1/comments/#{@comment.to_param}/edit + # collection_url # => /posts/1/comments + # parent_url # => /posts/1 + # + # # /projects/1/tasks + # resource_url # => /projects/1/tasks/#{@task.to_param} + # resource_url(task) # => /projects/1/tasks/#{task.to_param} + # new_resource_url # => /projects/1/tasks/new + # edit_resource_url # => /projects/1/tasks/#{@task.to_param}/edit + # collection_url # => /projects/1/tasks + # parent_url # => /projects/1 + # + # # /users + # resource_url # => /users/#{@user.to_param} + # resource_url(user) # => /users/#{user.to_param} + # new_resource_url # => /users/new + # edit_resource_url # => /users/#{@user.to_param}/edit + # collection_url # => /users + # parent_url # => / + # + # The nice thing is that those urls are not guessed during runtime. They are + # all created when you inherit. + # + module UrlHelpers + protected + + # This method hard code url helpers in the class. + # + # We are doing this because is cheaper than guessing them when our action + # is being processed (and even more cheaper when we are using nested + # resources). + # + # When we are using polymorphic associations, those helpers rely on + # polymorphic_url Rails helper. + # + def create_resources_url_helpers! + resource_segments, resource_ivars = [], [] + resource_config = self.resources_configuration[:self] + + singleton = self.resources_configuration[:self][:singleton] + polymorphic = self.parents_symbols.include?(:polymorphic) + + # Add route_prefix if any. + unless resource_config[:route_prefix].blank? + if polymorphic + resource_ivars << resource_config[:route_prefix].to_s.inspect + else + resource_segments << resource_config[:route_prefix] + end + end + + # Deal with belongs_to associations and polymorphic associations. + # Remember that we don't have to build the segments in polymorphic cases, + # because the url will be polymorphic_url. + # + self.parents_symbols.each do |symbol| + if symbol == :polymorphic + resource_ivars << :parent + else + config = self.resources_configuration[symbol] + resource_segments << config[:route_name] + resource_ivars << :"@#{config[:instance_name]}" + end + end + + collection_ivars = resource_ivars.dup + collection_segments = resource_segments.dup + + + # Generate parent url before we add resource instances. + unless parents_symbols.empty? + generate_url_and_path_helpers nil, :parent, resource_segments, resource_ivars + generate_url_and_path_helpers :edit, :parent, resource_segments, resource_ivars + end + + # This is the default route configuration, later we have to deal with + # exception from polymorphic and singleton cases. + # + collection_segments << resource_config[:route_collection_name] + resource_segments << resource_config[:route_instance_name] + resource_ivars << :"@#{resource_config[:instance_name]}" + + # In singleton cases, we do not send the current element instance variable + # because the id is not in the URL. For example, we should call: + # + # project_manager_url(@project) + # + # Instead of: + # + # project_manager_url(@project, @manager) + # + # Another exception in singleton cases is that collection url does not + # exist. In such cases, we create the parent collection url. So in the + # manager case above, the collection url will be: + # + # project_url(@project) + # + # If the singleton does not have a parent, it will default to root_url. + # + # Finally, polymorphic cases we have to give hints to the polymorphic url + # builder. This works by attaching new ivars as symbols or records. + # + if singleton + collection_segments.pop + resource_ivars.pop + + if polymorphic + resource_ivars << resource_config[:instance_name].inspect + new_ivars = resource_ivars + end + elsif polymorphic + collection_ivars << '(@_resource_class_new ||= resource_class.new)' + end + + # If route is uncountable then add "_index" suffix to collection index route name + # + if !singleton && resource_config[:route_collection_name] == resource_config[:route_instance_name] + collection_segments << :index + end + + generate_url_and_path_helpers nil, :collection, collection_segments, collection_ivars + generate_url_and_path_helpers :new, :resource, resource_segments, new_ivars || collection_ivars + generate_url_and_path_helpers nil, :resource, resource_segments, resource_ivars + generate_url_and_path_helpers :edit, :resource, resource_segments, resource_ivars + + if resource_config[:custom_actions] + [*resource_config[:custom_actions][:resource]].each do | method | + generate_url_and_path_helpers method, :resource, resource_segments, resource_ivars + end + [*resource_config[:custom_actions][:collection]].each do | method | + generate_url_and_path_helpers method, :resources, collection_segments, collection_ivars + end + end + end + + def handle_shallow_resource(prefix, name, segments, ivars) #:nodoc: + return segments, ivars unless self.resources_configuration[:self][:shallow] + case name + when :collection, :resources + segments = segments[-2..-1] + ivars = [ivars.last] + when :resource + if prefix == :new + segments = segments[-2..-1] + ivars = [ivars.last] + else + segments = [segments.last] + ivars = [ivars.last] + end + when :parent + segments = [segments.last] + ivars = [ivars.last] + end + + segments ||= [] + + unless self.resources_configuration[:self][:route_prefix].blank? + segments.unshift self.resources_configuration[:self][:route_prefix] + end + + return segments, ivars + end + + def generate_url_and_path_helpers(prefix, name, resource_segments, resource_ivars) #:nodoc: + resource_segments, resource_ivars = handle_shallow_resource(prefix, name, resource_segments, resource_ivars) + + ivars = resource_ivars.dup + singleton = self.resources_configuration[:self][:singleton] + polymorphic = self.parents_symbols.include?(:polymorphic) + + # If it's not a singleton, ivars are not empty, not a collection or + # not a "new" named route, we can pass a resource as argument. + # + unless (singleton && name != :parent) || ivars.empty? || name == :collection || prefix == :new + ivars.push "(given_args.first || #{ivars.pop})" + end + + # In collection in polymorphic cases, allow an argument to be given as a + # replacemente for the parent. + # + if name == :collection && polymorphic + index = ivars.index(:parent) + ivars.insert index, "(given_args.first || parent)" + ivars.delete(:parent) + end + + # When polymorphic is true, the segments must be replace by :polymorphic + # and ivars should be gathered into an array, which is compacted when + # optional. + # + if polymorphic + segments = :polymorphic + ivars = "[#{ivars.join(', ')}]" + ivars << '.compact' if self.resources_configuration[:polymorphic][:optional] + else + segments = resource_segments.empty? ? 'root' : resource_segments.join('_') + ivars = ivars.join(', ') + end + + prefix = prefix ? "#{prefix}_" : '' + ivars << (ivars.empty? ? 'given_options' : ', given_options') + + class_eval <<-URL_HELPERS, __FILE__, __LINE__ + protected + def #{prefix}#{name}_path(*given_args) + given_options = given_args.extract_options! + #{prefix}#{segments}_path(#{ivars}) + end + + def #{prefix}#{name}_url(*given_args) + given_options = given_args.extract_options! + #{prefix}#{segments}_url(#{ivars}) + end + URL_HELPERS + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/version.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/version.rb new file mode 100644 index 0000000..44ed35f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/lib/inherited_resources/version.rb @@ -0,0 +1,3 @@ +module InheritedResources + VERSION = '1.3.0'.freeze +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/aliases_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/aliases_test.rb new file mode 100644 index 0000000..bccedb5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/aliases_test.rb @@ -0,0 +1,153 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Student + extend ActiveModel::Naming +end + +class ApplicationController < ActionController::Base + include InheritedResources::DSL +end + +class StudentsController < ApplicationController + inherit_resources + respond_to :html, :xml + + def edit + edit! do |format| + format.xml { render :text => 'Render XML' } + end + end + + def new + @something = 'magical' + new! + end + + create!(:location => "http://test.host/") do |success, failure| + success.html { render :text => "I won't redirect!" } + failure.xml { render :text => "I shouldn't be rendered" } + end + + update! do |success, failure| + success.html { redirect_to(resource_url) } + failure.html { render :text => "I won't render!" } + end + + destroy! do |format| + format.html { render :text => "Destroyed!" } + end +end + +class AliasesTest < ActionController::TestCase + tests StudentsController + + def test_assignments_before_calling_alias + Student.stubs(:new).returns(mock_student) + get :new + assert_response :success + assert_equal 'magical', assigns(:something) + end + + def test_controller_should_render_new + Student.stubs(:new).returns(mock_student) + get :new + assert_response :success + assert_equal 'New HTML', @response.body.strip + end + + def test_expose_the_requested_user_on_edit + Student.expects(:find).with('42').returns(mock_student) + get :edit, :id => '42' + assert_equal mock_student, assigns(:student) + assert_response :success + end + + def test_controller_should_render_edit + Student.stubs(:find).returns(mock_student) + get :edit + assert_response :success + assert_equal 'Edit HTML', @response.body.strip + end + + def test_render_xml_when_it_is_given_as_a_block + @request.accept = 'application/xml' + Student.stubs(:find).returns(mock_student) + get :edit + assert_response :success + assert_equal 'Render XML', @response.body + end + + def test_is_not_redirected_on_create_with_success_if_success_block_is_given + Student.stubs(:new).returns(mock_student(:save => true)) + @controller.stubs(:resource_url).returns('http://test.host/') + post :create + assert_response :success + assert_equal "I won't redirect!", @response.body + end + + def test_dumb_responder_quietly_receives_everything_on_failure + @request.accept = 'text/html' + Student.stubs(:new).returns(mock_student(:save => false, :errors => {:some => :error})) + @controller.stubs(:resource_url).returns('http://test.host/') + post :create + assert_response :success + assert_equal "New HTML", @response.body.strip + end + + def test_html_is_the_default_when_only_xml_is_overwriten + @request.accept = '*/*' + Student.stubs(:new).returns(mock_student(:save => false, :errors => {:some => :error})) + @controller.stubs(:resource_url).returns('http://test.host/') + post :create + assert_response :success + assert_equal "New HTML", @response.body.strip + end + + def test_wont_render_edit_template_on_update_with_failure_if_failure_block_is_given + Student.stubs(:find).returns(mock_student(:update_attributes => false, :errors => { :fail => true })) + put :update + assert_response :success + assert_equal "I won't render!", @response.body + end + + def test_dumb_responder_quietly_receives_everything_on_success + Student.stubs(:find).returns(mock_student(:update_attributes => true)) + @controller.stubs(:resource_url).returns('http://test.host/') + put :update, :id => '42', :student => {:these => 'params'} + assert_equal mock_student, assigns(:student) + end + + def test_block_is_called_when_student_is_destroyed + Student.stubs(:find).returns(mock_student(:destroy => true)) + delete :destroy + assert_response :success + assert_equal "Destroyed!", @response.body + end + + def test_options_are_used_in_respond_with + @request.accept = "application/xml" + mock_student = mock_student(:save => true, :to_xml => "XML") + Student.stubs(:new).returns(mock_student) + + # Bug in mocha does not accept strings on respond_to + mock_student.singleton_class.class_eval do + def respond_to?(method, *) + method == "to_xml" || super + end + end + + post :create + assert_equal "http://test.host/", @response.location + end + + protected + def mock_student(expectations={}) + @mock_student ||= begin + student = mock(expectations.except(:errors)) + student.stubs(:class).returns(Student) + student.stubs(:errors).returns(expectations.fetch(:errors, {})) + student + end + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/association_chain_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/association_chain_test.rb new file mode 100644 index 0000000..b8e1eb6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/association_chain_test.rb @@ -0,0 +1,125 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Pet + extend ActiveModel::Naming +end + +class Puppet + extend ActiveModel::Naming +end + +class PetsController < InheritedResources::Base + attr_accessor :current_user + + def edit + @pet = 'new pet' + edit! + end + + protected + def collection + @pets ||= end_of_association_chain.all + end + + def begin_of_association_chain + @current_user + end +end + +class BeginOfAssociationChainTest < ActionController::TestCase + tests PetsController + + def setup + @controller.current_user = mock() + end + + def test_begin_of_association_chain_is_called_on_index + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:all).returns(mock_pet) + get :index + assert_response :success + assert_equal 'Index HTML', @response.body.strip + end + + def test_begin_of_association_chain_is_called_on_new + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:build).returns(mock_pet) + get :new + assert_response :success + assert_equal 'New HTML', @response.body.strip + end + + def test_begin_of_association_chain_is_called_on_show + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:find).with('47').returns(mock_pet) + get :show, :id => '47' + assert_response :success + assert_equal 'Show HTML', @response.body.strip + end + + def test_instance_variable_should_not_be_set_if_already_defined + @controller.current_user.expects(:pets).never + Pet.expects(:find).never + get :edit + assert_response :success + assert_equal 'new pet', assigns(:pet) + end + + def test_model_is_not_initialized_with_nil + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:build).with({}).returns(mock_pet) + get :new + assert_equal mock_pet, assigns(:pet) + end + + def test_begin_of_association_chain_is_included_in_chain + @controller.current_user.expects(:pets).returns(Pet) + Pet.expects(:build).with({}).returns(mock_pet) + get :new + assert_equal [@controller.current_user], @controller.send(:association_chain) + end + + protected + def mock_pet(stubs={}) + @mock_pet ||= mock(stubs) + end + +end + +class PuppetsController < InheritedResources::Base + optional_belongs_to :pet +end + +class AssociationChainTest < ActionController::TestCase + tests PuppetsController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_parent_is_added_to_association_chain + Pet.expects(:find).with('37').returns(mock_pet) + mock_pet.expects(:puppets).returns(Puppet) + Puppet.expects(:find).with('42').returns(mock_puppet) + mock_puppet.expects(:destroy) + delete :destroy, :id => '42', :pet_id => '37' + assert_equal [mock_pet], @controller.send(:association_chain) + end + + def test_parent_is_added_to_association_chain_if_not_available + Puppet.expects(:find).with('42').returns(mock_puppet) + mock_puppet.expects(:destroy) + delete :destroy, :id => '42' + assert_equal [], @controller.send(:association_chain) + end + + protected + def mock_pet(stubs={}) + @mock_pet ||= mock(stubs) + end + + def mock_puppet(stubs={}) + @mock_puppet ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/base_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/base_test.rb new file mode 100644 index 0000000..685a46e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/base_test.rb @@ -0,0 +1,331 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class User + extend ActiveModel::Naming +end + +class AccountsController < InheritedResources::Base +end + +class UsersController < AccountsController + respond_to :html, :xml + respond_to :js, :only => [:create, :update, :destroy] + attr_reader :scopes_applied + +protected + + def apply_scopes(object) + @scopes_applied = true + object + end +end + +module UserTestHelper + def setup + @controller = UsersController.new + @controller.request = @request = ActionController::TestRequest.new + @controller.response = @response = ActionController::TestResponse.new + @controller.stubs(:user_url).returns("/") + end + + protected + + def mock_user(expectations={}) + @mock_user ||= begin + user = mock(expectations.except(:errors)) + user.stubs(:class).returns(User) + user.stubs(:errors).returns(expectations.fetch(:errors, {})) + user.singleton_class.class_eval do + def method_missing(symbol, *arguments, &block) + raise NoMethodError.new('this is expected by Array#flatten') if symbol == :to_ary + super + end + end + user + end + end +end + +class IndexActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_all_users_as_instance_variable + User.expects(:scoped).returns([mock_user]) + get :index + assert_equal [mock_user], assigns(:users) + end + + def test_apply_scopes_if_method_is_available + User.expects(:scoped).returns([mock_user]) + get :index + assert @controller.scopes_applied + end + + def test_controller_should_render_index + User.stubs(:scoped).returns([mock_user]) + get :index + assert_response :success + assert_equal 'Index HTML', @response.body.strip + end + + def test_render_all_users_as_xml_when_mime_type_is_xml + @request.accept = 'application/xml' + User.expects(:scoped).returns(collection = [mock_user]) + collection.expects(:to_xml).returns('Generated XML') + get :index + assert_response :success + assert_equal 'Generated XML', @response.body + end + + def test_scoped_is_called_only_when_available + User.stubs(:all).returns([mock_user]) + get :index + assert_equal Array, assigns(:users).class + end +end + +class ShowActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_the_requested_user + User.expects(:find).with('42').returns(mock_user) + get :show, :id => '42' + assert_equal mock_user, assigns(:user) + end + + def test_controller_should_render_show + User.stubs(:find).returns(mock_user) + get :show + assert_response :success + assert_equal 'Show HTML', @response.body.strip + end + + def test_render_exposed_user_as_xml_when_mime_type_is_xml + @request.accept = 'application/xml' + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:to_xml).returns("Generated XML") + + # Bug in mocha does not accept strings on respond_to + mock_user.singleton_class.class_eval do + def respond_to?(method, *) + method == "to_xml" || super + end + end + + get :show, :id => '42' + assert_response :success + assert_equal 'Generated XML', @response.body + end +end + +class NewActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_a_new_user + User.expects(:new).returns(mock_user) + get :new + assert_equal mock_user, assigns(:user) + end + + def test_controller_should_render_new + User.stubs(:new).returns(mock_user) + get :new + assert_response :success + assert_equal 'New HTML', @response.body.strip + end + + def test_render_exposed_a_new_user_as_xml_when_mime_type_is_xml + @request.accept = 'application/xml' + User.expects(:new).returns(mock_user) + mock_user.expects(:to_xml).returns("Generated XML") + + # Bug in mocha does not accept strings on respond_to + mock_user.singleton_class.class_eval do + def respond_to?(method, *) + method == "to_xml" || super + end + end + + get :new + assert_response :success + assert_equal 'Generated XML', @response.body + end +end + +class EditActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_the_requested_user + User.expects(:find).with('42').returns(mock_user) + get :edit, :id => '42' + assert_response :success + assert_equal mock_user, assigns(:user) + end + + def test_controller_should_render_edit + User.stubs(:find).returns(mock_user) + get :edit + assert_response :success + assert_equal 'Edit HTML', @response.body.strip + end +end + +class CreateActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_expose_a_newly_create_user_when_saved_with_success + User.expects(:new).with({'these' => 'params'}).returns(mock_user(:save => true)) + post :create, :user => {:these => 'params'} + assert_equal mock_user, assigns(:user) + end + + def test_expose_a_newly_create_user_when_saved_with_success_and_role_setted + @controller.class.send(:with_role, :admin) + User.expects(:new).with({'these' => 'params'}, {:as => :admin}).returns(mock_user(:save => true)) + post :create, :user => {:these => 'params'} + assert_equal mock_user, assigns(:user) + @controller.class.send(:with_role, nil) + end + + def test_redirect_to_the_created_user + User.stubs(:new).returns(mock_user(:save => true)) + @controller.expects(:resource_url).returns('http://test.host/') + post :create + assert_redirected_to 'http://test.host/' + end + + def test_show_flash_message_when_success + User.stubs(:new).returns(mock_user(:save => true)) + post :create + assert_equal flash[:notice], 'User was successfully created.' + end + + def test_show_flash_message_with_javascript_request_when_success + User.stubs(:new).returns(mock_user(:save => true)) + post :create, :format => :js + assert_equal flash[:notice], 'User was successfully created.' + end + + def test_render_new_template_when_user_cannot_be_saved + User.stubs(:new).returns(mock_user(:save => false, :errors => {:some => :error})) + post :create + assert_response :success + assert_equal "New HTML", @response.body.strip + end + + def test_dont_show_flash_message_when_user_cannot_be_saved + User.stubs(:new).returns(mock_user(:save => false, :errors => {:some => :error})) + post :create + assert flash.empty? + end +end + +class UpdateActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_update_the_requested_object + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :user => {:these => 'params'} + assert_equal mock_user, assigns(:user) + end + + def test_update_the_requested_object_when_setted_role + @controller.class.send(:with_role, :admin) + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:update_attributes).with({'these' => 'params'}, {:as => :admin}).returns(true) + put :update, :id => '42', :user => {:these => 'params'} + assert_equal mock_user, assigns(:user) + @controller.class.send(:with_role, nil) + end + + def test_redirect_to_the_updated_user + User.stubs(:find).returns(mock_user(:update_attributes => true)) + @controller.expects(:resource_url).returns('http://test.host/') + put :update + assert_redirected_to 'http://test.host/' + end + + def test_redirect_to_the_users_list_if_show_undefined + @controller.class.send(:actions, :all, :except => :show) + User.stubs(:find).returns(mock_user(:update_attributes => true)) + @controller.expects(:collection_url).returns('http://test.host/') + put :update + assert_redirected_to 'http://test.host/' + end + + def test_show_flash_message_when_success + User.stubs(:find).returns(mock_user(:update_attributes => true)) + put :update + assert_equal flash[:notice], 'User was successfully updated.' + end + + def test_show_flash_message_with_javascript_request_when_success + User.stubs(:find).returns(mock_user(:update_attributes => true)) + post :update, :format => :js + assert_equal flash[:notice], 'User was successfully updated.' + end + + def test_render_edit_template_when_user_cannot_be_saved + User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => {:some => :error})) + put :update + assert_response :success + assert_equal "Edit HTML", @response.body.strip + end + + def test_dont_show_flash_message_when_user_cannot_be_saved + User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => {:some => :error})) + put :update + assert flash.empty? + end +end + +class DestroyActionBaseTest < ActionController::TestCase + include UserTestHelper + + def test_the_requested_user_is_destroyed + User.expects(:find).with('42').returns(mock_user) + mock_user.expects(:destroy).returns(true) + delete :destroy, :id => '42' + assert_equal mock_user, assigns(:user) + end + + def test_show_flash_message_when_user_can_be_deleted + User.stubs(:find).returns(mock_user(:destroy => true)) + delete :destroy + assert_equal flash[:notice], 'User was successfully destroyed.' + end + + def test_show_flash_message_with_javascript_request_when_user_can_be_deleted + User.stubs(:find).returns(mock_user(:destroy => true)) + delete :destroy, :format => :js + assert_equal flash[:notice], 'User was successfully destroyed.' + end + + def test_show_flash_message_when_user_cannot_be_deleted + User.stubs(:find).returns(mock_user(:destroy => false, :errors => { :fail => true })) + delete :destroy + assert_equal flash[:alert], 'User could not be destroyed.' + end + + def test_show_flash_message_with_javascript_request_when_user_cannot_be_deleted + User.stubs(:find).returns(mock_user(:destroy => false, :errors => { :fail => true })) + delete :destroy, :format => :js + assert_equal flash[:alert], 'User could not be destroyed.' + end + + def test_redirects_to_users_list + User.stubs(:find).returns(mock_user(:destroy => true)) + @controller.expects(:collection_url).returns('http://test.host/') + delete :destroy + assert_redirected_to 'http://test.host/' + end + + def test_redirects_to_the_resource_if_cannot_be_destroyed + User.stubs(:find).returns(mock_user(:destroy => false)) + @controller.expects(:collection_url).returns('http://test.host/') + delete :destroy + assert_redirected_to 'http://test.host/' + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/belongs_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/belongs_to_test.rb new file mode 100644 index 0000000..fdb38db --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/belongs_to_test.rb @@ -0,0 +1,130 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Post + extend ActiveModel::Naming +end + +class Comment + extend ActiveModel::Naming +end + +class CommentsController < InheritedResources::Base + belongs_to :post +end + +class BelongsToTest < ActionController::TestCase + tests CommentsController + + def setup + Post.expects(:find).with('37').returns(mock_post) + mock_post.expects(:comments).returns(Comment) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_comments_as_instance_variable_on_index + Comment.expects(:scoped).returns([mock_comment]) + get :index, :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal [mock_comment], assigns(:comments) + end + + def test_expose_the_requested_comment_on_show + Comment.expects(:find).with('42').returns(mock_comment) + get :show, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_expose_a_new_comment_on_new + Comment.expects(:build).returns(mock_comment) + get :new, :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_expose_the_requested_comment_on_edit + Comment.expects(:find).with('42').returns(mock_comment) + get :edit, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_redirect_to_the_post_on_update_if_show_and_index_undefined + @controller.class.send(:actions, :all, :except => [:show, :index]) + @controller.expects(:parent_url).returns('http://test.host/') + Comment.expects(:build).with({'these' => 'params'}).returns(mock_comment(:save => true)) + post :create, :post_id => '37', :comment => {:these => 'params'} + assert_redirected_to 'http://test.host/' + end + + def test_expose_a_newly_create_comment_on_create + Comment.expects(:build).with({'these' => 'params'}).returns(mock_comment(:save => true)) + post :create, :post_id => '37', :comment => {:these => 'params'} + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_redirect_to_the_post_on_update_if_show_and_index_undefined + @controller.class.send(:actions, :all, :except => [:show, :index]) + Comment.stubs(:find).returns(mock_comment(:update_attributes => true)) + @controller.expects(:parent_url).returns('http://test.host/') + put :update, :id => '42', :post_id => '37', :comment => {:these => 'params'} + assert_redirected_to 'http://test.host/' + end + + def test_update_the_requested_object_on_update + Comment.expects(:find).with('42').returns(mock_comment) + mock_comment.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :post_id => '37', :comment => {:these => 'params'} + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def test_redirect_to_the_post_on_destroy_if_show_and_index_undefined + @controller.class.send(:actions, :all, :except => [:show, :index]) + Comment.expects(:find).with('42').returns(mock_comment) + mock_comment.expects(:destroy) + @controller.expects(:parent_url).returns('http://test.host/') + delete :destroy, :id => '42', :post_id => '37' + assert_redirected_to 'http://test.host/' + end + + def test_the_requested_comment_is_destroyed_on_destroy + Comment.expects(:find).with('42').returns(mock_comment) + mock_comment.expects(:destroy) + delete :destroy, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_comment, assigns(:comment) + end + + def helper_methods + @controller.class._helpers.instance_methods.map {|m| m.to_s } + end + + def test_helpers + mock_post.stubs(:class).returns(Post) + + Comment.expects(:scoped).returns([mock_comment]) + get :index, :post_id => '37' + + assert helper_methods.include?('parent?') + assert @controller.send(:parent?) + assert_equal mock_post, assigns(:post) + assert helper_methods.include?('parent') + assert_equal mock_post, @controller.send(:parent) + end + + protected + + def mock_post(stubs={}) + @mock_post ||= mock(stubs) + end + + def mock_comment(stubs={}) + @mock_comment ||= mock(stubs) + end + +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/belongs_to_with_shallow_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/belongs_to_with_shallow_test.rb new file mode 100644 index 0000000..3b98234 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/belongs_to_with_shallow_test.rb @@ -0,0 +1,93 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Post + extend ActiveModel::Naming +end + +class Tag + extend ActiveModel::Naming +end + +class TagsController < InheritedResources::Base + belongs_to :post, :shallow => true, :finder => :find_by_slug +end + +class BelongsToWithShallowTest < ActionController::TestCase + tests TagsController + + def setup + Post.expects(:find_by_slug).with('thirty_seven').returns(mock_post) + mock_post.expects(:tags).returns(Tag) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_tags_as_instance_variable_on_index + Tag.expects(:scoped).returns([mock_tag]) + get :index, :post_id => 'thirty_seven' + assert_equal mock_post, assigns(:post) + assert_equal [mock_tag], assigns(:tags) + end + + def test_expose_a_new_tag_on_new + Tag.expects(:build).returns(mock_tag) + get :new, :post_id => 'thirty_seven' + assert_equal mock_post, assigns(:post) + assert_equal mock_tag, assigns(:tag) + end + + def test_expose_a_newly_create_tag_on_create + Tag.expects(:build).with({'these' => 'params'}).returns(mock_tag(:save => true)) + post :create, :post_id => 'thirty_seven', :tag => {:these => 'params'} + assert_equal mock_post, assigns(:post) + assert_equal mock_tag, assigns(:tag) + end + + def test_expose_the_requested_tag_on_show + should_find_parents + get :show, :id => '42' + assert_equal mock_post, assigns(:post) + assert_equal mock_tag, assigns(:tag) + end + + def test_expose_the_requested_tag_on_edit + should_find_parents + get :edit, :id => '42' + assert_equal mock_post, assigns(:post) + assert_equal mock_tag, assigns(:tag) + end + + def test_update_the_requested_object_on_update + should_find_parents + mock_tag.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :tag => {:these => 'params'} + assert_equal mock_post, assigns(:post) + assert_equal mock_tag, assigns(:tag) + end + + def test_the_requested_tag_is_destroyed_on_destroy + should_find_parents + mock_tag.expects(:destroy) + delete :destroy, :id => '42', :post_id => '37' + assert_equal mock_post, assigns(:post) + assert_equal mock_tag, assigns(:tag) + end + + protected + def should_find_parents + mock_tag.expects(:post).returns(mock_post) + mock_post.expects(:to_param).returns('thirty_seven') + Tag.expects(:find).with('42').twice.returns(mock_tag) + end + + def mock_post(stubs={}) + @mock_post ||= mock(stubs) + end + + def mock_tag(stubs={}) + @mock_tag ||= mock(stubs) + end + +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/class_methods_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/class_methods_test.rb new file mode 100644 index 0000000..8756b03 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/class_methods_test.rb @@ -0,0 +1,134 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Book; end +class Folder; end + +class BooksController < InheritedResources::Base + custom_actions :collection => :search, :resource => [:delete] + actions :index, :show +end + +class ReadersController < InheritedResources::Base + actions :all, :except => [ :edit, :update ] +end + +class FoldersController < InheritedResources::Base +end + +class Dean + def self.human_name; 'Dean'; end +end + +class DeansController < InheritedResources::Base + belongs_to :school +end + +class ActionsClassMethodTest < ActionController::TestCase + tests BooksController + + def test_cannot_render_actions + assert_raise ActionController::UnknownAction do + get :new + end + end + + def test_actions_are_undefined + action_methods = BooksController.send(:action_methods).map(&:to_sym) + assert_equal 4, action_methods.size + + [:index, :show, :delete, :search].each do |action| + assert action_methods.include?(action) + end + + instance_methods = BooksController.send(:instance_methods).map(&:to_sym) + + [:new, :edit, :create, :update, :destroy].each do |action| + assert !instance_methods.include?(action) + end + end + + def test_actions_are_undefined_when_except_option_is_given + action_methods = ReadersController.send(:action_methods) + assert_equal 5, action_methods.size + + ['index', 'new', 'show', 'create', 'destroy'].each do |action| + assert action_methods.include? action + end + end + +end + +class DefaultsClassMethodTest < ActiveSupport::TestCase + def test_resource_class_is_set_to_nil_when_resource_model_cannot_be_found + assert_nil ReadersController.send(:resource_class) + end + + def test_defaults_are_set + assert_equal Folder, FoldersController.send(:resource_class) + assert_equal :folder, FoldersController.send(:resources_configuration)[:self][:instance_name] + assert_equal :folders, FoldersController.send(:resources_configuration)[:self][:collection_name] + end + + def test_defaults_can_be_overwriten + BooksController.send(:defaults, :resource_class => String, :instance_name => 'string', :collection_name => 'strings') + + assert_equal String, BooksController.send(:resource_class) + assert_equal :string, BooksController.send(:resources_configuration)[:self][:instance_name] + assert_equal :strings, BooksController.send(:resources_configuration)[:self][:collection_name] + + BooksController.send(:defaults, :class_name => 'Fixnum', :instance_name => :fixnum, :collection_name => :fixnums) + + assert_equal Fixnum, BooksController.send(:resource_class) + assert_equal :fixnum, BooksController.send(:resources_configuration)[:self][:instance_name] + assert_equal :fixnums, BooksController.send(:resources_configuration)[:self][:collection_name] + end + + def test_defaults_raises_invalid_key + assert_raise ArgumentError do + BooksController.send(:defaults, :boom => String) + end + end + + def test_url_helpers_are_recreated_when_defaults_change + BooksController.expects(:create_resources_url_helpers!).returns(true).once + BooksController.send(:defaults, :instance_name => 'string', :collection_name => 'strings') + end +end + +class BelongsToErrorsTest < ActiveSupport::TestCase + def test_belongs_to_raise_errors_with_invalid_arguments + assert_raise ArgumentError do + DeansController.send(:belongs_to) + end + + assert_raise ArgumentError do + DeansController.send(:belongs_to, :nice, :invalid_key => '') + end + end + + def test_belongs_to_raises_an_error_when_multiple_associations_are_given_with_options + assert_raise ArgumentError do + DeansController.send(:belongs_to, :arguments, :with_options, :parent_class => Professor) + end + end + + def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_block + DeansController.expects(:create_resources_url_helpers!).returns(true).once + DeansController.send(:belongs_to, :school) do + belongs_to :association + end + ensure + DeansController.send(:parents_symbols=, [:school]) + end + + def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_multiple_blocks + DeansController.expects(:create_resources_url_helpers!).returns(true).once + DeansController.send(:belongs_to, :school) do + belongs_to :association do + belongs_to :nested + end + end + ensure + DeansController.send(:parents_symbols=, [:school]) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_base_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_base_test.rb new file mode 100644 index 0000000..ac1dee2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_base_test.rb @@ -0,0 +1,168 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Car + extend ActiveModel::Naming +end + +class CarsController < InheritedResources::Base + respond_to :html + + protected + + def collection + @cars ||= Car.get_all + end + + def build_resource + @car ||= Car.create_new(params[:car]) + end + + def resource + @car ||= Car.get(params[:id]) + end + + def create_resource(resource) + resource.save_successfully + end + + def update_resource(resource, attributes) + resource.update_successfully(*attributes) + end + + def destroy_resource(resource) + resource.destroy_successfully + end +end + +module CarTestHelper + def setup + @controller = CarsController.new + @controller.request = @request = ActionController::TestRequest.new + @controller.response = @response = ActionController::TestResponse.new + @controller.stubs(:car_url).returns("/") + end + + protected + def mock_car(expectations={}) + @mock_car ||= begin + car = mock(expectations.except(:errors)) + car.stubs(:class).returns(Car) + car.stubs(:errors).returns(expectations.fetch(:errors, {})) + car + end + end +end + +class IndexActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_expose_all_users_as_instance_variable + Car.expects(:get_all).returns([mock_car]) + get :index + assert_equal [mock_car], assigns(:cars) + end +end + +class ShowActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_expose_the_requested_user + Car.expects(:get).with('42').returns(mock_car) + get :show, :id => '42' + assert_equal mock_car, assigns(:car) + end +end + +class NewActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_expose_a_new_user + Car.expects(:create_new).returns(mock_car) + get :new + assert_equal mock_car, assigns(:car) + end +end + +class EditActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_expose_the_requested_user + Car.expects(:get).with('42').returns(mock_car) + get :edit, :id => '42' + assert_response :success + assert_equal mock_car, assigns(:car) + end +end + +class CreateActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_expose_a_newly_create_user_when_saved_with_success + Car.expects(:create_new).with({'these' => 'params'}).returns(mock_car(:save_successfully => true)) + post :create, :car => {:these => 'params'} + assert_equal mock_car, assigns(:car) + end + + def test_redirect_to_the_created_user + Car.stubs(:create_new).returns(mock_car(:save_successfully => true)) + @controller.expects(:resource_url).returns('http://test.host/') + post :create + assert_redirected_to 'http://test.host/' + end + + def test_render_new_template_when_user_cannot_be_saved + Car.stubs(:create_new).returns(mock_car(:save_successfully => false, :errors => {:some => :error})) + post :create + assert_response :success + assert_equal "New HTML", @response.body.strip + end +end + +class UpdateActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_update_the_requested_object + Car.expects(:get).with('42').returns(mock_car) + mock_car.expects(:update_successfully).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :car => {:these => 'params'} + assert_equal mock_car, assigns(:car) + end + + def test_redirect_to_the_created_user + Car.stubs(:get).returns(mock_car(:update_successfully => true)) + @controller.expects(:resource_url).returns('http://test.host/') + put :update + assert_redirected_to 'http://test.host/' + end + + def test_render_edit_template_when_user_cannot_be_saved + Car.stubs(:get).returns(mock_car(:update_successfully => false, :errors => {:some => :error})) + put :update + assert_response :success + assert_equal "Edit HTML", @response.body.strip + end +end + +class DestroyActionCustomizedBaseTest < ActionController::TestCase + include CarTestHelper + + def test_the_requested_user_is_destroyed + Car.expects(:get).with('42').returns(mock_car) + mock_car.expects(:destroy_successfully) + delete :destroy, :id => '42' + assert_equal mock_car, assigns(:car) + end + + def test_show_flash_message_when_user_can_be_deleted + Car.stubs(:get).returns(mock_car(:destroy_successfully => true)) + delete :destroy + assert_equal flash[:notice], 'Car was successfully destroyed.' + end + + def test_show_flash_message_when_cannot_be_deleted + Car.stubs(:get).returns(mock_car(:destroy_successfully => false, :errors => { :fail => true })) + delete :destroy + assert_equal flash[:alert], 'Car could not be destroyed.' + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_belongs_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_belongs_to_test.rb new file mode 100644 index 0000000..384b123 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_belongs_to_test.rb @@ -0,0 +1,76 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class GreatSchool +end + +class Professor + def self.human_name; 'Professor'; end +end + +class ProfessorsController < InheritedResources::Base + belongs_to :school, :parent_class => GreatSchool, :instance_name => :great_school, + :finder => :find_by_title!, :param => :school_title +end + +class CustomizedBelongsToTest < ActionController::TestCase + tests ProfessorsController + + def setup + GreatSchool.expects(:find_by_title!).with('nice').returns(mock_school(:professors => Professor)) + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_index + Professor.stubs(:scoped).returns([mock_professor]) + get :index, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_show + Professor.stubs(:find).returns(mock_professor) + get :show, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_new + Professor.stubs(:build).returns(mock_professor) + get :new, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_edit + Professor.stubs(:find).returns(mock_professor) + get :edit, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_create + Professor.stubs(:build).returns(mock_professor(:save => true)) + post :create, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_update + Professor.stubs(:find).returns(mock_professor(:update_attributes => true)) + put :update, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + def test_expose_the_requested_school_with_chosen_instance_variable_on_destroy + Professor.stubs(:find).returns(mock_professor(:destroy => true)) + delete :destroy, :school_title => 'nice' + assert_equal mock_school, assigns(:great_school) + end + + protected + + def mock_school(stubs={}) + @mock_school ||= mock(stubs) + end + + def mock_professor(stubs={}) + @mock_professor ||= mock(stubs) + end +end + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_redirect_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_redirect_to_test.rb new file mode 100644 index 0000000..c708216 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/customized_redirect_to_test.rb @@ -0,0 +1,32 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Post; + def self.human_name; 'Post'; end +end + +class PostsController < InheritedResources::Base + actions :all, :except => [:show] +end + +class RedirectToIndexWithoutShowTest < ActionController::TestCase + tests PostsController + + def test_redirect_index_url_after_create + Post.stubs(:new).returns(mock_machine(:save => true)) + assert !PostsController.respond_to?(:show) + post :create + assert_redirected_to 'http://test.host/posts' + end + + def test_redirect_to_index_url_after_update + Post.stubs(:find).returns(mock_machine(:update_attributes => true)) + assert !PostsController.respond_to?(:show) + put :update + assert_redirected_to 'http://test.host/posts' + end + + protected + def mock_machine(stubs={}) + @mock_machine ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/defaults_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/defaults_test.rb new file mode 100644 index 0000000..c5aa641 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/defaults_test.rb @@ -0,0 +1,197 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Malarz + def self.human_name; 'Painter'; end + + def to_param + self.slug + end +end + +class PaintersController < InheritedResources::Base + defaults :instance_name => 'malarz', :collection_name => 'malarze', + :resource_class => Malarz, :route_prefix => nil, + :finder => :find_by_slug +end + +class DefaultsTest < ActionController::TestCase + tests PaintersController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_painters_as_instance_variable + Malarz.expects(:scoped).returns([mock_painter]) + get :index + assert_equal [mock_painter], assigns(:malarze) + end + + def test_expose_the_requested_painter_on_show + Malarz.expects(:find_by_slug).with('forty_two').returns(mock_painter) + get :show, :id => 'forty_two' + assert_equal mock_painter, assigns(:malarz) + end + + def test_expose_a_new_painter + Malarz.expects(:new).returns(mock_painter) + get :new + assert_equal mock_painter, assigns(:malarz) + end + + def test_expose_the_requested_painter_on_edit + Malarz.expects(:find_by_slug).with('forty_two').returns(mock_painter) + get :edit, :id => 'forty_two' + assert_response :success + assert_equal mock_painter, assigns(:malarz) + end + + def test_expose_a_newly_create_painter_when_saved_with_success + Malarz.expects(:new).with({'these' => 'params'}).returns(mock_painter(:save => true)) + post :create, :malarz => {:these => 'params'} + assert_equal mock_painter, assigns(:malarz) + end + + def test_update_the_requested_object + Malarz.expects(:find_by_slug).with('forty_two').returns(mock_painter) + mock_painter.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => 'forty_two', :malarz => {:these => 'params'} + assert_equal mock_painter, assigns(:malarz) + end + + def test_the_requested_painter_is_destroyed + Malarz.expects(:find_by_slug).with('forty_two').returns(mock_painter) + mock_painter.expects(:destroy) + delete :destroy, :id => 'forty_two' + assert_equal mock_painter, assigns(:malarz) + end + + protected + def mock_painter(stubs={}) + @mock_painter ||= mock(stubs) + end +end + +class Professor + def self.human_name; 'Einstein'; end +end +module University; end +class University::ProfessorsController < InheritedResources::Base + defaults :finder => :find_by_slug +end + +class DefaultsNamespaceTest < ActionController::TestCase + tests University::ProfessorsController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_professors_as_instance_variable + Professor.expects(:scoped).returns([mock_professor]) + get :index + assert_equal [mock_professor], assigns(:professors) + end + + def test_expose_the_requested_painter_on_show + Professor.expects(:find_by_slug).with('forty_two').returns(mock_professor) + get :show, :id => 'forty_two' + assert_equal mock_professor, assigns(:professor) + end + + def test_expose_a_new_painter + Professor.expects(:new).returns(mock_professor) + get :new + assert_equal mock_professor, assigns(:professor) + end + + def test_expose_the_requested_painter_on_edit + Professor.expects(:find_by_slug).with('forty_two').returns(mock_professor) + get :edit, :id => 'forty_two' + assert_response :success + assert_equal mock_professor, assigns(:professor) + end + + def test_expose_a_newly_create_professor_when_saved_with_success + Professor.expects(:new).with({'these' => 'params'}).returns(mock_professor(:save => true)) + post :create, :professor => {:these => 'params'} + assert_equal mock_professor, assigns(:professor) + end + + def test_update_the_professor + Professor.expects(:find_by_slug).with('forty_two').returns(mock_professor) + mock_professor.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => 'forty_two', :professor => {:these => 'params'} + assert_equal mock_professor, assigns(:professor) + end + + def test_the_requested_painter_is_destroyed + Professor.expects(:find_by_slug).with('forty_two').returns(mock_professor) + mock_professor.expects(:destroy) + delete :destroy, :id => 'forty_two' + assert_equal mock_professor, assigns(:professor) + end + + protected + def mock_professor(stubs={}) + @mock_professor ||= mock(stubs) + end +end + +class Group +end +class AdminGroup +end +module Admin; end +class Admin::Group +end +class Admin::GroupsController < InheritedResources::Base +end +class NamespacedModelForNamespacedController < ActionController::TestCase + tests Admin::GroupsController + + def test_that_it_picked_the_namespaced_model + # make public so we can test it + Admin::GroupsController.send(:public, *Admin::GroupsController.protected_instance_methods) + assert_equal Admin::Group, @controller.resource_class + end +end + +class Role +end +class AdminRole +end +class Admin::RolesController < InheritedResources::Base +end +class TwoPartNameModelForNamespacedController < ActionController::TestCase + tests Admin::RolesController + + def test_that_it_picked_the_camelcased_model + # make public so we can test it + Admin::RolesController.send(:public, *Admin::RolesController.protected_instance_methods) + assert_equal AdminRole, @controller.resource_class + end +end + +class User +end +class Admin::UsersController < InheritedResources::Base +end +class TwoPartNameModelForNamespacedController < ActionController::TestCase + tests Admin::UsersController + + def setup + # make public so we can test it + Admin::UsersController.send(:public, *Admin::UsersController.protected_instance_methods) + end + + def test_that_it_picked_the_camelcased_model + assert_equal User, @controller.resource_class + end + + def test_that_it_got_the_rquest_params_right + assert_equal 'user', @controller.resources_configuration[:self][:request_name] + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/locales/en.yml b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/locales/en.yml new file mode 100644 index 0000000..258a71c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/locales/en.yml @@ -0,0 +1,17 @@ +en: + flash: + addresses: + create: + notice: "You created a new address close to {{reference}}." + update: + notice: "Nice! {{resource_name}} was updated with success!" + error: "Oh no! We could not update your address!" + admin: + actions: + create: + notice: "Admin notice message." + error: "Admin error message." + addresses: + create: + notice: "Admin, you created a new address close to {{reference}}." + diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/multiple_nested_optional_belongs_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/multiple_nested_optional_belongs_to_test.rb new file mode 100644 index 0000000..8d2ac5a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/multiple_nested_optional_belongs_to_test.rb @@ -0,0 +1,369 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Student; end +class Manager; end +class Employee; end + +class Project + def self.human_name; "Project"; end +end + +class ProjectsController < InheritedResources::Base + belongs_to :student, :manager, :employee, :optional => true +end + +class MultipleNestedOptionalTest < ActionController::TestCase + tests ProjectsController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + # INDEX + def test_expose_all_projects_as_instance_variable_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:scoped).returns([mock_project]) + get :index, :student_id => '37' + assert_equal mock_student, assigns(:student) + assert_equal [mock_project], assigns(:projects) + end + + def test_expose_all_projects_as_instance_variable_with_manager + Manager.expects(:find).with('38').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:scoped).returns([mock_project]) + get :index, :manager_id => '38' + assert_equal mock_manager, assigns(:manager) + assert_equal [mock_project], assigns(:projects) + end + + def test_expose_all_projects_as_instance_variable_with_employee + Employee.expects(:find).with('666').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:scoped).returns([mock_project]) + get :index, :employee_id => '666' + assert_equal mock_employee, assigns(:employee) + assert_equal [mock_project], assigns(:projects) + end + + def test_expose_all_projects_as_instance_variable_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:scoped).returns([mock_project]) + get :index, :manager_id => '37', :employee_id => '42' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal [mock_project], assigns(:projects) + end + + def test_expose_all_projects_as_instance_variable_without_parents + Project.expects(:scoped).returns([mock_project]) + get :index + assert_equal [mock_project], assigns(:projects) + end + + # SHOW + def test_expose_the_requested_project_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + get :show, :id => '42', :student_id => '37' + assert_equal mock_student, assigns(:student) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_with_manager + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + get :show, :id => '42', :manager_id => '37' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_with_employee + Employee.expects(:find).with('37').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + get :show, :id => '42', :employee_id => '37' + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('13').returns(mock_project) + get :show, :id => '13', :manager_id => '37', :employee_id => '42' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_without_parents + Project.expects(:find).with('13').returns(mock_project) + get :show, :id => '13' + assert_equal mock_project, assigns(:project) + end + + # NEW + def test_expose_a_new_project_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:build).returns(mock_project) + get :new, :student_id => '37' + assert_equal mock_student, assigns(:student) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_new_project_with_manager + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:build).returns(mock_project) + get :new, :manager_id => '37' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_new_project_with_employee + Employee.expects(:find).with('37').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:build).returns(mock_project) + get :new, :employee_id => '37' + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_new_project_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:build).returns(mock_project) + get :new, :manager_id => '37', :employee_id => '42' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_new_project_without_parents + Project.expects(:new).returns(mock_project) + get :new + assert_equal mock_project, assigns(:project) + end + + # EDIT + def test_expose_the_requested_project_for_edition_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + get :edit, :id => '42', :student_id => '37' + assert_equal mock_student, assigns(:student) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_for_edition_with_manager + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + get :edit, :id => '42', :manager_id => '37' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_for_edition_with_employee + Employee.expects(:find).with('37').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + get :edit, :id => '42', :employee_id => '37' + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_for_edition_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('13').returns(mock_project) + get :edit, :id => '13', :manager_id => '37', :employee_id => '42' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_the_requested_project_for_edition_without_parents + Project.expects(:find).with('13').returns(mock_project) + get :edit, :id => '13' + assert_equal mock_project, assigns(:project) + end + + # CREATE + def test_expose_a_newly_created_project_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:build).with({ 'these' => 'params' }).returns(mock_project(:save => true)) + post :create, :student_id => '37', :project => { :these => 'params' } + assert_equal mock_student, assigns(:student) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_newly_created_project_with_manager + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:build).with({ 'these' => 'params' }).returns(mock_project(:save => true)) + post :create, :manager_id => '37', :project => { :these => 'params' } + assert_equal mock_manager, assigns(:manager) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_newly_created_project_with_employee + Employee.expects(:find).with('37').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:build).with({ 'these' => 'params' }).returns(mock_project(:save => true)) + post :create, :employee_id => '37', :project => { :these => 'params' } + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_newly_created_project_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:build).with({ 'these' => 'params' }).returns(mock_project(:save => true)) + post :create, :manager_id => '37', :employee_id => '42', :project => { :these => 'params' } + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_expose_a_newly_created_project_without_parents + Project.expects(:new).with({ 'these' => 'params' }).returns(mock_project(:save => true)) + post :create, :project => { :these => 'params' } + assert_equal mock_project, assigns(:project) + end + + # UPDATE + def test_update_the_requested_project_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:update_attributes).with({ 'these' => 'params' }).returns(true) + put :update, :id => '42', :student_id => '37', :project => { :these => 'params' } + assert_equal mock_student, assigns(:student) + assert_equal mock_project, assigns(:project) + end + + def test_update_the_requested_project_with_manager + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:update_attributes).with({ 'these' => 'params' }).returns(true) + put :update, :id => '42', :manager_id => '37', :project => { :these => 'params' } + assert_equal mock_manager, assigns(:manager) + assert_equal mock_project, assigns(:project) + end + + def test_update_the_requested_project_with_employee + Employee.expects(:find).with('37').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:update_attributes).with({ 'these' => 'params' }).returns(true) + put :update, :id => '42', :employee_id => '37', :project => { :these => 'params' } + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_update_the_requested_project_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('13').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:update_attributes).with({ 'these' => 'params' }).returns(true) + put :update, :id => '42', :manager_id => '37', :employee_id => '13', :project => { :these => 'params' } + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + # DESTROY + def test_the_requested_project_is_destroyed_with_student + Student.expects(:find).with('37').returns(mock_student) + mock_student.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:destroy).returns(true) + + delete :destroy, :id => '42', :student_id => '37' + assert_equal mock_student, assigns(:student) + assert_equal mock_project, assigns(:project) + end + + def test_the_requested_project_is_destroyed_with_manager + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:destroy).returns(true) + + delete :destroy, :id => '42', :manager_id => '37' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_project, assigns(:project) + end + + def test_the_requested_project_is_destroyed_with_employee + Employee.expects(:find).with('37').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:destroy).returns(true) + + delete :destroy, :id => '42', :employee_id => '37' + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_the_requested_project_is_destroyed_with_manager_and_employee + Manager.expects(:find).with('37').returns(mock_manager) + mock_manager.expects(:employees).returns(Employee) + Employee.expects(:find).with('13').returns(mock_employee) + mock_employee.expects(:projects).returns(Project) + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:destroy).returns(true) + + delete :destroy, :id => '42', :manager_id => '37', :employee_id => '13' + assert_equal mock_manager, assigns(:manager) + assert_equal mock_employee, assigns(:employee) + assert_equal mock_project, assigns(:project) + end + + def test_the_requested_project_is_destroyed_without_parents + Project.expects(:find).with('42').returns(mock_project) + mock_project.expects(:destroy).returns(true) + + delete :destroy, :id => '42' + assert_equal mock_project, assigns(:project) + end + + protected + def mock_manager(stubs={}) + @mock_manager ||= mock(stubs) + end + + def mock_employee(stubs={}) + @mock_employee ||= mock(stubs) + end + + def mock_student(stubs={}) + @mock_student ||= mock(stubs) + end + + def mock_project(stubs={}) + @mock_project ||= mock(stubs) + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_belongs_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_belongs_to_test.rb new file mode 100644 index 0000000..9805430 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_belongs_to_test.rb @@ -0,0 +1,108 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Country +end + +class State +end + +class City + def self.human_name; 'City'; end +end + +class CitiesController < InheritedResources::Base + belongs_to :country, :state +end + +class NestedBelongsToTest < ActionController::TestCase + tests CitiesController + + def setup + Country.expects(:find).with('13').returns(mock_country) + mock_country.expects(:states).returns(State) + State.expects(:find).with('37').returns(mock_state) + mock_state.expects(:cities).returns(City) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_assigns_country_and_state_and_city_on_create + City.expects(:find).with(:all).returns([mock_city]) + get :index, :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal [mock_city], assigns(:cities) + end + + def test_assigns_country_and_state_and_city_on_show + City.expects(:find).with('42').returns(mock_city) + get :show, :id => '42', :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_new + City.expects(:build).returns(mock_city) + get :new, :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_edit + City.expects(:find).with('42').returns(mock_city) + get :edit, :id => '42', :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_create + City.expects(:build).with({'these' => 'params'}).returns(mock_city) + mock_city.expects(:save).returns(true) + post :create, :state_id => '37', :country_id => '13', :city => {:these => 'params'} + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_update + City.expects(:find).with('42').returns(mock_city) + mock_city.expects(:update_attributes).returns(true) + put :update, :id => '42', :state_id => '37', :country_id => '13', :city => {:these => 'params'} + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + def test_assigns_country_and_state_and_city_on_destroy + City.expects(:find).with('42').returns(mock_city) + mock_city.expects(:destroy) + delete :destroy, :id => '42', :state_id => '37', :country_id => '13' + + assert_equal mock_country, assigns(:country) + assert_equal mock_state, assigns(:state) + assert_equal mock_city, assigns(:city) + end + + protected + def mock_country(stubs={}) + @mock_country ||= mock(stubs) + end + + def mock_state(stubs={}) + @mock_state ||= mock(stubs) + end + + def mock_city(stubs={}) + @mock_city ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_belongs_to_with_shallow_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_belongs_to_with_shallow_test.rb new file mode 100644 index 0000000..9085442 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_belongs_to_with_shallow_test.rb @@ -0,0 +1,123 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Dresser +end + +class Shelf +end + +class Plate +end + +class PlatesController < InheritedResources::Base + belongs_to :dresser, :shelf, :shallow => true +end + +class NestedBelongsToWithShallowTest < ActionController::TestCase + tests PlatesController + + def setup + mock_shelf.expects(:dresser).returns(mock_dresser) + mock_dresser.expects(:to_param).returns('13') + + Dresser.expects(:find).with('13').returns(mock_dresser) + mock_dresser.expects(:shelves).returns(Shelf) + mock_shelf.expects(:plates).returns(Plate) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_assigns_dresser_and_shelf_and_plate_on_index + Shelf.expects(:find).with('37').twice.returns(mock_shelf) + Plate.expects(:scoped).returns([mock_plate]) + get :index, :shelf_id => '37' + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal [mock_plate], assigns(:plates) + end + + def test_assigns_dresser_and_shelf_and_plate_on_show + should_find_parents + get :show, :id => '42' + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal mock_plate, assigns(:plate) + end + + def test_assigns_dresser_and_shelf_and_plate_on_new + Plate.expects(:build).returns(mock_plate) + Shelf.expects(:find).with('37').twice.returns(mock_shelf) + get :new, :shelf_id => '37' + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal mock_plate, assigns(:plate) + end + + def test_assigns_dresser_and_shelf_and_plate_on_edit + should_find_parents + get :edit, :id => '42' + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal mock_plate, assigns(:plate) + end + + + def test_assigns_dresser_and_shelf_and_plate_on_create + Shelf.expects(:find).with('37').twice.returns(mock_shelf) + + Plate.expects(:build).with({'these' => 'params'}).returns(mock_plate) + mock_plate.expects(:save).returns(true) + post :create, :shelf_id => '37', :plate => {:these => 'params'} + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal mock_plate, assigns(:plate) + end + + def test_assigns_dresser_and_shelf_and_plate_on_update + should_find_parents + mock_plate.expects(:update_attributes).returns(true) + put :update, :id => '42', :plate => {:these => 'params'} + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal mock_plate, assigns(:plate) + end + + def test_assigns_dresser_and_shelf_and_plate_on_destroy + should_find_parents + mock_plate.expects(:destroy) + delete :destroy, :id => '42' + + assert_equal mock_dresser, assigns(:dresser) + assert_equal mock_shelf, assigns(:shelf) + assert_equal mock_plate, assigns(:plate) + end + + + protected + def should_find_parents + Plate.expects(:find).with('42').returns(mock_plate) + mock_plate.expects(:shelf).returns(mock_shelf) + mock_shelf.expects(:to_param).returns('37') + Plate.expects(:find).with('42').returns(mock_plate) + Shelf.expects(:find).with('37').returns(mock_shelf) + end + + def mock_dresser(stubs={}) + @mock_dresser ||= mock(stubs) + end + + def mock_shelf(stubs={}) + @mock_shelf ||= mock(stubs) + end + + def mock_plate(stubs={}) + @mock_plate ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_model_with_shallow_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_model_with_shallow_test.rb new file mode 100644 index 0000000..deb4aad --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/nested_model_with_shallow_test.rb @@ -0,0 +1,147 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Subfaculty +end + +class Speciality +end + +module Plan + class Group + end + + class Education + end +end + +class GroupsController < InheritedResources::Base + defaults :resource_class => Plan::Group, :finder => :find_by_slug + belongs_to :subfaculty, :shallow => true do + belongs_to :speciality + end +end + +class EducationsController < InheritedResources::Base + defaults :resource_class => Plan::Education + belongs_to :subfaculty, :shallow => true do + belongs_to :speciality do + belongs_to :group, :parent_class => Plan::Group, + :instance_name => :plan_group, + :param => :group_id, + :finder => :find_by_slug + end + end +end + +class NestedModelWithShallowTest < ActionController::TestCase + tests GroupsController + + def setup + mock_speciality.expects(:subfaculty).returns(mock_subfaculty) + mock_subfaculty.expects(:to_param).returns('13') + + Subfaculty.expects(:find).with('13').returns(mock_subfaculty) + mock_subfaculty.expects(:specialities).returns(Speciality) + mock_speciality.expects(:groups).returns(Plan::Group) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_assigns_subfaculty_and_speciality_and_group_on_edit + should_find_parents + get :edit, :id => 'forty_two' + + assert_equal mock_subfaculty, assigns(:subfaculty) + assert_equal mock_speciality, assigns(:speciality) + assert_equal mock_group, assigns(:group) + end + + def test_expose_a_newly_create_group_with_speciality + Speciality.expects(:find).with('37').twice.returns(mock_speciality) + Plan::Group.expects(:build).with({'these' => :params}).returns(mock_group(:save => true)) + post :create, :speciality_id => '37', :group => {:these => :params} + assert_equal mock_group, assigns(:group) + end + + def test_expose_a_update_group_with_speciality + should_find_parents + mock_group.expects(:update_attributes).with('these' => :params).returns(true) + post :update, :id => 'forty_two', :group => {:these => :params} + assert_equal mock_group, assigns(:group) + end + + protected + def should_find_parents + Plan::Group.expects(:find_by_slug).with('forty_two').returns(mock_group) + mock_group.expects(:speciality).returns(mock_speciality) + mock_speciality.expects(:to_param).returns('37') + Plan::Group.expects(:find_by_slug).with('forty_two').returns(mock_group) + Speciality.expects(:find).with('37').returns(mock_speciality) + end + + def mock_group(stubs={}) + @mock_group ||= mock(stubs) + end + + def mock_speciality(stubs={}) + @mock_speciality ||= mock(stubs) + end + + def mock_subfaculty(stubs={}) + @mock_subfaculty ||= mock(stubs) + end +end + +class TwoNestedModelWithShallowTest < ActionController::TestCase + tests EducationsController + + def setup + mock_speciality.expects(:subfaculty).returns(mock_subfaculty) + mock_subfaculty.expects(:to_param).returns('13') + Subfaculty.expects(:find).with('13').returns(mock_subfaculty) + mock_subfaculty.expects(:specialities).returns(Speciality) + mock_speciality.expects(:groups).returns(Plan::Group) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_assigns_subfaculty_and_speciality_and_group_on_new + should_find_parents + get :new, :group_id => 'forty_two' + + assert_equal mock_subfaculty, assigns(:subfaculty) + assert_equal mock_speciality, assigns(:speciality) + assert_equal mock_group, assigns(:plan_group) + assert_equal mock_education, assigns(:education) + end + + + protected + def should_find_parents + Plan::Group.expects(:find_by_slug).with('forty_two').returns(mock_group) + mock_group.expects(:speciality).returns(mock_speciality) + mock_group.expects(:educations).returns(mock_education) + mock_education.expects(:build).returns(mock_education) + mock_speciality.expects(:to_param).returns('37') + Plan::Group.expects(:find_by_slug).with('forty_two').returns(mock_group) + Speciality.expects(:find).with('37').returns(mock_speciality) + end + + def mock_group(stubs={}) + @mock_group ||= mock(stubs) + end + + def mock_education(stubs={}) + @mock_education ||= mock(stubs) + end + + def mock_speciality(stubs={}) + @mock_speciality ||= mock(stubs) + end + + def mock_subfaculty(stubs={}) + @mock_subfaculty ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/optional_belongs_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/optional_belongs_to_test.rb new file mode 100644 index 0000000..78993ed --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/optional_belongs_to_test.rb @@ -0,0 +1,164 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Brands; end +class Category; end + +class Product + def self.human_name; 'Product'; end +end + +class ProductsController < InheritedResources::Base + belongs_to :brand, :category, :polymorphic => true, :optional => true +end + +class OptionalTest < ActionController::TestCase + tests ProductsController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_products_as_instance_variable_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:scoped).returns([mock_product]) + get :index, :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal [mock_product], assigns(:products) + end + + def test_expose_all_products_as_instance_variable_without_category + Product.expects(:scoped).returns([mock_product]) + get :index + assert_equal nil, assigns(:category) + assert_equal [mock_product], assigns(:products) + end + + def test_expose_the_requested_product_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + get :show, :id => '42', :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_the_requested_product_without_category + Product.expects(:find).with('42').returns(mock_product) + get :show, :id => '42' + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_new_product_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:build).returns(mock_product) + get :new, :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_new_product_without_category + Product.expects(:new).returns(mock_product) + get :new + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_the_requested_product_for_edition_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + get :edit, :id => '42', :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_the_requested_product_for_edition_without_category + Product.expects(:find).with('42').returns(mock_product) + get :edit, :id => '42' + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_newly_create_product_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:build).with({'these' => 'params'}).returns(mock_product(:save => true)) + post :create, :category_id => '37', :product => {:these => 'params'} + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_expose_a_newly_create_product_without_category + Product.expects(:new).with({'these' => 'params'}).returns(mock_product(:save => true)) + post :create, :product => {:these => 'params'} + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_update_the_requested_object_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:update_attributes).with({'these' => 'params'}).returns(true) + + put :update, :id => '42', :category_id => '37', :product => {:these => 'params'} + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_update_the_requested_object_without_category + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:update_attributes).with({'these' => 'params'}).returns(true) + + put :update, :id => '42', :product => {:these => 'params'} + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_the_requested_product_is_destroyed_with_category + Category.expects(:find).with('37').returns(mock_category) + mock_category.expects(:products).returns(Product) + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:destroy).returns(true) + @controller.expects(:collection_url).returns('/') + + delete :destroy, :id => '42', :category_id => '37' + assert_equal mock_category, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_the_requested_product_is_destroyed_without_category + Product.expects(:find).with('42').returns(mock_product) + mock_product.expects(:destroy).returns(true) + @controller.expects(:collection_url).returns('/') + + delete :destroy, :id => '42' + assert_equal nil, assigns(:category) + assert_equal mock_product, assigns(:product) + end + + def test_polymorphic_helpers + Product.expects(:scoped).returns([mock_product]) + get :index + + assert !@controller.send(:parent?) + assert_equal nil, assigns(:parent_type) + assert_equal nil, @controller.send(:parent_type) + assert_equal nil, @controller.send(:parent_class) + assert_equal nil, assigns(:category) + assert_equal nil, @controller.send(:parent) + end + + protected + def mock_category(stubs={}) + @mock_category ||= mock(stubs) + end + + def mock_product(stubs={}) + @mock_product ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/polymorphic_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/polymorphic_test.rb new file mode 100644 index 0000000..41958b1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/polymorphic_test.rb @@ -0,0 +1,186 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Factory; end +class Company; end + +class Employee + def self.human_name; 'Employee'; end +end + +class EmployeesController < InheritedResources::Base + belongs_to :factory, :company, :polymorphic => true +end + +class PolymorphicFactoriesTest < ActionController::TestCase + tests EmployeesController + + def setup + Factory.expects(:find).with('37').returns(mock_factory) + mock_factory.expects(:employees).returns(Employee) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_employees_as_instance_variable_on_index + Employee.expects(:scoped).returns([mock_employee]) + get :index, :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal [mock_employee], assigns(:employees) + end + + def test_expose_the_requested_employee_on_show + Employee.expects(:find).with('42').returns(mock_employee) + get :show, :id => '42', :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_a_new_employee_on_new + Employee.expects(:build).returns(mock_employee) + get :new, :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_the_requested_employee_on_edit + Employee.expects(:find).with('42').returns(mock_employee) + get :edit, :id => '42', :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + assert_response :success + end + + def test_expose_a_newly_create_employee_on_create + Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true)) + post :create, :factory_id => '37', :employee => {:these => 'params'} + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_update_the_requested_object_on_update + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :factory_id => '37', :employee => {:these => 'params'} + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_the_requested_employee_is_destroyed_on_destroy + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:destroy) + delete :destroy, :id => '42', :factory_id => '37' + assert_equal mock_factory, assigns(:factory) + assert_equal mock_employee, assigns(:employee) + end + + def test_polymorphic_helpers + mock_factory.stubs(:class).returns(Factory) + + Employee.expects(:scoped).returns([mock_employee]) + get :index, :factory_id => '37' + + assert @controller.send(:parent?) + assert_equal :factory, assigns(:parent_type) + assert_equal :factory, @controller.send(:parent_type) + assert_equal Factory, @controller.send(:parent_class) + assert_equal mock_factory, assigns(:factory) + assert_equal mock_factory, @controller.send(:parent) + end + + protected + def mock_factory(stubs={}) + @mock_factory ||= mock(stubs) + end + + def mock_employee(stubs={}) + @mock_employee ||= mock(stubs) + end +end + +class PolymorphicCompanyTest < ActionController::TestCase + tests EmployeesController + + def setup + Company.expects(:find).with('37').returns(mock_company) + mock_company.expects(:employees).returns(Employee) + + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_all_employees_as_instance_variable_on_index + Employee.expects(:scoped).returns([mock_employee]) + get :index, :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal [mock_employee], assigns(:employees) + end + + def test_expose_the_requested_employee_on_show + Employee.expects(:find).with('42').returns(mock_employee) + get :show, :id => '42', :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_a_new_employee_on_new + Employee.expects(:build).returns(mock_employee) + get :new, :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_expose_the_requested_employee_on_edit + Employee.expects(:find).with('42').returns(mock_employee) + get :edit, :id => '42', :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + assert_response :success + end + + def test_expose_a_newly_create_employee_on_create + Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true)) + post :create, :company_id => '37', :employee => {:these => 'params'} + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_update_the_requested_object_on_update + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :id => '42', :company_id => '37', :employee => {:these => 'params'} + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_the_requested_employee_is_destroyed_on_destroy + Employee.expects(:find).with('42').returns(mock_employee) + mock_employee.expects(:destroy) + delete :destroy, :id => '42', :company_id => '37' + assert_equal mock_company, assigns(:company) + assert_equal mock_employee, assigns(:employee) + end + + def test_polymorphic_helpers + mock_company.stubs(:class).returns(Company) + + Employee.expects(:scoped).returns([mock_employee]) + get :index, :company_id => '37' + + assert @controller.send(:parent?) + assert_equal :company, assigns(:parent_type) + assert_equal :company, @controller.send(:parent_type) + assert_equal Company, @controller.send(:parent_class) + assert_equal mock_company, assigns(:company) + assert_equal mock_company, @controller.send(:parent) + end + + protected + def mock_company(stubs={}) + @mock_company ||= mock(stubs) + end + + def mock_employee(stubs={}) + @mock_employee ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/redirect_to_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/redirect_to_test.rb new file mode 100644 index 0000000..1cc0c73 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/redirect_to_test.rb @@ -0,0 +1,51 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Machine; + def self.human_name; 'Machine'; end +end + +class MachinesController < InheritedResources::Base + def create + create!{ complex_url(:create, true, true) } + end + + def update + update!{ complex_url(:update, false, false) } + end + + def destroy + destroy!{ complex_url(:destroy, true, false) } + end + + protected + def complex_url(name, arg2, arg3) + 'http://test.host/' + name.to_s + end +end + +class RedirectToWithBlockTest < ActionController::TestCase + tests MachinesController + + def test_redirect_to_the_given_url_on_create + Machine.stubs(:new).returns(mock_machine(:save => true)) + post :create + assert_redirected_to 'http://test.host/create' + end + + def test_redirect_to_the_given_url_on_update + Machine.stubs(:find).returns(mock_machine(:update_attributes => true)) + put :update + assert_redirected_to 'http://test.host/update' + end + + def test_redirect_to_the_given_url_on_destroy + Machine.stubs(:find).returns(mock_machine(:destroy => true)) + delete :destroy + assert_redirected_to 'http://test.host/destroy' + end + + protected + def mock_machine(stubs={}) + @mock_machine ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/singleton_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/singleton_test.rb new file mode 100644 index 0000000..eb0188b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/singleton_test.rb @@ -0,0 +1,86 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +# This test file is instead to test the how controller flow and actions +# using a belongs_to association. This is done using mocks a la rspec. +# +class Store + extend ActiveModel::Naming +end + +class Manager + extend ActiveModel::Naming +# def self.human_name; 'Manager'; end +end + +class ManagersController < InheritedResources::Base + belongs_to :store, :singleton => true +end + +class SingletonTest < ActionController::TestCase + tests ManagersController + + def setup + @controller.stubs(:resource_url).returns('/') + @controller.stubs(:collection_url).returns('/') + end + + def test_expose_the_requested_manager_on_show + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:manager).returns(mock_manager) + get :show, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_expose_a_new_manager_on_new + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:build_manager).returns(mock_manager) + get :new, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_expose_the_requested_manager_on_edit + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:manager).returns(mock_manager) + get :edit, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + assert_response :success + end + + def test_expose_a_newly_create_manager_on_create + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:build_manager).with({'these' => 'params'}).returns(mock_manager(:save => true)) + post :create, :store_id => '37', :manager => {:these => 'params'} + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_update_the_requested_object_on_update + Store.expects(:find).with('37').returns(mock_store(:manager => mock_manager)) + mock_manager.expects(:update_attributes).with({'these' => 'params'}).returns(true) + put :update, :store_id => '37', :manager => {:these => 'params'} + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + def test_the_requested_manager_is_destroyed_on_destroy + Store.expects(:find).with('37').returns(mock_store) + mock_store.expects(:manager).returns(mock_manager) + @controller.expects(:parent_url).returns('http://test.host/') + mock_manager.expects(:destroy) + delete :destroy, :store_id => '37' + assert_equal mock_store, assigns(:store) + assert_equal mock_manager, assigns(:manager) + end + + protected + def mock_store(stubs={}) + @mock_store ||= mock(stubs) + end + + def mock_manager(stubs={}) + @mock_manager ||= mock(stubs) + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/test_helper.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/test_helper.rb new file mode 100644 index 0000000..31903b4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/test_helper.rb @@ -0,0 +1,45 @@ +require 'rubygems' +require 'bundler' + +Bundler.setup + +require 'test/unit' +require 'mocha' + +ENV["RAILS_ENV"] = "test" +RAILS_ROOT = "anywhere" + +require "active_support" +require "active_model" +require "action_controller" + +I18n.load_path << File.join(File.dirname(__FILE__), 'locales', 'en.yml') +I18n.reload! + +class ApplicationController < ActionController::Base; end + +# Add IR to load path and load the main file +$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') +require 'inherited_resources' + +ActionController::Base.view_paths = File.join(File.dirname(__FILE__), 'views') + +InheritedResources::Routes = ActionDispatch::Routing::RouteSet.new +InheritedResources::Routes.draw do + match ':controller(/:action(/:id))' + match ':controller(/:action)' + resources 'posts' + root :to => 'posts#index' +end + +ActionController::Base.send :include, InheritedResources::Routes.url_helpers + +# Add app base to load path +$:.unshift File.expand_path(File.dirname(__FILE__) + '/../app/controllers') +require 'inherited_resources/base' + +class ActiveSupport::TestCase + setup do + @routes = InheritedResources::Routes + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/url_helpers_test.rb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/url_helpers_test.rb new file mode 100644 index 0000000..39ecc38 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/url_helpers_test.rb @@ -0,0 +1,812 @@ +require File.expand_path('test_helper', File.dirname(__FILE__)) + +class Universe + extend ActiveModel::Naming +end +class UniversesController < InheritedResources::Base + defaults :singleton => true, :route_instance_name => 'universum' +end + +class House + extend ActiveModel::Naming +end +class HousesController < InheritedResources::Base +end + +class News + extend ActiveModel::Naming +end +class NewsController < InheritedResources::Base +end + +class Backpack + extend ActiveModel::Naming +end +module Admin; end +class Admin::BackpacksController < InheritedResources::Base + defaults :route_collection_name => 'tour_backpacks' +end + +class Table + extend ActiveModel::Naming +end +class TablesController < InheritedResources::Base + belongs_to :house +end + +class RoomsController < InheritedResources::Base + belongs_to :house, :route_name => 'big_house' +end + +class ChairsController < InheritedResources::Base + belongs_to :house do + belongs_to :table + end +end + +class OwnersController < InheritedResources::Base + singleton_belongs_to :house +end + +class Bed + extend ActiveModel::Naming +end +class BedsController < InheritedResources::Base + optional_belongs_to :house, :building +end + +class Sheep + extend ActiveModel::Naming +end +class SheepController < InheritedResources::Base + belongs_to :news, :table, :polymorphic => true +end + +class Desk + extend ActiveModel::Naming +end +module Admin + class DesksController < InheritedResources::Base + optional_belongs_to :house + end +end + +class Dish + extend ActiveModel::Naming +end +class DishesController < InheritedResources::Base + belongs_to :house do + polymorphic_belongs_to :table, :kitchen + end +end + +class Center + extend ActiveModel::Naming +end +class CentersController < InheritedResources::Base + acts_as_singleton! + + belongs_to :house do + belongs_to :table, :kitchen, :polymorphic => true + end +end + +class Mirror + extend ActiveModel::Naming +end +class MirrorsController < InheritedResources::Base + belongs_to :house, :shallow => true +end +class Admin::MirrorsController < InheritedResources::Base + belongs_to :house, :shallow => true +end + + +class Display + extend ActiveModel::Naming +end + +class Window + extend ActiveModel::Naming +end + +class Button + extend ActiveModel::Naming +end + +class ButtonsController < InheritedResources::Base + belongs_to :display, :window, :shallow => true + custom_actions :resource => :delete, :collection => :search +end + +class ImageButtonsController < ButtonsController +end + + +# Create a TestHelper module with some helpers +class UrlHelpersTest < ActiveSupport::TestCase + def mock_polymorphic(controller, route) + controller.expects(:url_for).with(:no=>"no") + controller._routes.url_helpers.expects("hash_for_#{route}").returns({:no=>"no"}) + end + + def test_url_helpers_on_simple_inherited_resource + controller = HousesController.new + controller.instance_variable_set('@house', :house) + + [:url, :path].each do |path_or_url| + controller.expects("houses_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With arg + controller.expects("house_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("house_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + # With options + controller.expects("house_#{path_or_url}").with(:arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_simple_inherited_resource_using_uncountable + controller = NewsController.new + controller.instance_variable_set('@news', :news) + + [:url, :path].each do |path_or_url| + controller.expects("news_index_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("news_#{path_or_url}").with(:news, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_news_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_news_#{path_or_url}").with(:news, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With arg + controller.expects("news_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("news_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + # With options + controller.expects("news_#{path_or_url}").with(:arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_simple_inherited_namespaced_resource + controller = Admin::BackpacksController.new + controller.instance_variable_set('@backpack', :backpack) + + assert_equal 'admin', controller.class.resources_configuration[:self][:route_prefix] + + [:url, :path].each do |path_or_url| + controller.expects("admin_tour_backpacks_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("admin_backpack_#{path_or_url}").with(:backpack, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_admin_backpack_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_admin_backpack_#{path_or_url}").with(:backpack, {}).once + controller.send("edit_resource_#{path_or_url}") + + # With arg + controller.expects("admin_backpack_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("admin_backpack_#{path_or_url}").with(:arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + # With options + controller.expects("admin_backpack_#{path_or_url}").with(:arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_simple_inherited_singleton_resource + controller = UniversesController.new + controller.instance_variable_set('@universe', :universe) + + [:url, :path].each do |path_or_url| + controller.expects("root_#{path_or_url}").with({}).once + controller.send("collection_#{path_or_url}") + + controller.expects("universum_#{path_or_url}").with({}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_universum_#{path_or_url}").with({}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_universum_#{path_or_url}").with({}).once + controller.send("edit_resource_#{path_or_url}") + + # With options + # Also tests that argument sent are not used + controller.expects("universum_#{path_or_url}").with(:page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_belongs_to + controller = TablesController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@table', :table) + + [:url, :path].each do |path_or_url| + controller.expects("house_tables_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_table_#{path_or_url}").with(:house, :table, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_table_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_table_#{path_or_url}").with(:house, :table, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_parent_#{path_or_url}") + + # With arg + controller.expects("house_table_#{path_or_url}").with(:house, :arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("edit_house_table_#{path_or_url}").with(:house, :arg, {}).once + controller.send("edit_resource_#{path_or_url}", :arg) + + controller.expects("house_#{path_or_url}").with(:arg, {}).once + controller.send("parent_#{path_or_url}", :arg) + + # With options + controller.expects("house_table_#{path_or_url}").with(:house, :arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_not_default_belongs_to + controller = RoomsController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@room', :room) + + [:url, :path].each do |path_or_url| + controller.expects("big_house_rooms_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("big_house_room_#{path_or_url}").with(:house, :room, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_big_house_room_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_big_house_room_#{path_or_url}").with(:house, :room, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("big_house_#{path_or_url}").with(:house, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_big_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_parent_#{path_or_url}") + + # With args + controller.expects("big_house_room_#{path_or_url}").with(:house, :arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("edit_big_house_room_#{path_or_url}").with(:house, :arg, {}).once + controller.send("edit_resource_#{path_or_url}", :arg) + + controller.expects("big_house_#{path_or_url}").with(:arg, {}).once + controller.send("parent_#{path_or_url}", :arg) + + # With options + controller.expects("big_house_room_#{path_or_url}").with(:house, :arg, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_nested_belongs_to + controller = ChairsController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@table', :table) + controller.instance_variable_set('@chair', :chair) + + [:url, :path].each do |path_or_url| + controller.expects("house_table_chairs_#{path_or_url}").with(:house, :table, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_table_chair_#{path_or_url}").with(:house, :table, :chair, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_table_chair_#{path_or_url}").with(:house, :table, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :chair, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("house_table_#{path_or_url}").with(:house, :table, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_house_table_#{path_or_url}").with(:house, :table, {}).once + controller.send("edit_parent_#{path_or_url}") + + # With args + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :arg, {}).once + controller.send("edit_resource_#{path_or_url}", :arg) + + controller.expects("house_table_chair_#{path_or_url}").with(:house, :table, :arg, {}).once + controller.send("resource_#{path_or_url}", :arg) + + controller.expects("house_table_#{path_or_url}").with(:house, :arg, {}).once + controller.send("parent_#{path_or_url}", :arg) + + # With options + controller.expects("edit_house_table_chair_#{path_or_url}").with(:house, :table, :arg, :page => 1).once + controller.send("edit_resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_singletons_with_belongs_to + controller = OwnersController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@owner', :owner) + + [:url, :path].each do |path_or_url| + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("house_owner_#{path_or_url}").with(:house, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_owner_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_house_owner_#{path_or_url}").with(:house, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_parent_#{path_or_url}") + + # With options + # Also tests that argument sent are not used + controller.expects("house_owner_#{path_or_url}").with(:house, :page => 1).once + controller.send("resource_#{path_or_url}", :arg, :page => 1) + end + end + + def test_url_helpers_on_polymorphic_belongs_to + house = House.new + bed = Bed.new + + new_bed = Bed.new + Bed.stubs(:new).returns(new_bed) + new_bed.stubs(:persisted?).returns(false) + + controller = BedsController.new + controller.instance_variable_set('@parent_type', :house) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@bed', bed) + + [:url, :path].each do |path_or_url| + mock_polymorphic(controller, "house_beds_#{path_or_url}").with(house).once + controller.send("collection_#{path_or_url}") + + mock_polymorphic(controller, "house_bed_#{path_or_url}").with(house, bed).once + controller.send("resource_#{path_or_url}") + + mock_polymorphic(controller, "new_house_bed_#{path_or_url}").with(house).once + controller.send("new_resource_#{path_or_url}") + + mock_polymorphic(controller, "edit_house_bed_#{path_or_url}").with(house, bed).once + controller.send("edit_resource_#{path_or_url}") + + mock_polymorphic(controller, "house_#{path_or_url}").with(house).once + controller.send("parent_#{path_or_url}") + + mock_polymorphic(controller, "edit_house_#{path_or_url}").with(house).once + controller.send("edit_parent_#{path_or_url}") + end + + # With options + mock_polymorphic(controller, "house_bed_url").with(house, bed, :page => 1).once + controller.send("resource_url", :page => 1) + + mock_polymorphic(controller, "house_url").with(house, :page => 1).once + controller.send("parent_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([:arg, new_bed], {}).once + controller.send("collection_url", :arg) + + controller.expects("polymorphic_url").with([house, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([house, :arg], {}).once + controller.send("edit_resource_url", :arg) + + controller.expects("polymorphic_url").with([:arg], {}).once + controller.send("parent_url", :arg) + end + + def test_url_helpers_on_polymorphic_belongs_to_using_uncountable + sheep = Sheep.new + news = News.new + + new_sheep = Sheep.new + Sheep.stubs(:new).returns(new_sheep) + new_sheep.stubs(:persisted?).returns(false) + + controller = SheepController.new + controller.instance_variable_set('@parent_type', :news) + controller.instance_variable_set('@news', news) + controller.instance_variable_set('@sheep', sheep) + + [:url, :path].each do |path_or_url| + mock_polymorphic(controller, "news_sheep_index_#{path_or_url}").with(news).once + controller.send("collection_#{path_or_url}") + + mock_polymorphic(controller, "news_sheep_#{path_or_url}").with(news, sheep).once + controller.send("resource_#{path_or_url}") + + mock_polymorphic(controller, "new_news_sheep_#{path_or_url}").with(news).once + controller.send("new_resource_#{path_or_url}") + + mock_polymorphic(controller, "edit_news_sheep_#{path_or_url}").with(news, sheep).once + controller.send("edit_resource_#{path_or_url}") + + mock_polymorphic(controller, "news_#{path_or_url}").with(news).once + controller.send("parent_#{path_or_url}") + + mock_polymorphic(controller, "edit_news_#{path_or_url}").with(news).once + controller.send("edit_parent_#{path_or_url}") + end + + # With options + mock_polymorphic(controller, "news_sheep_url").with(news, sheep, :page => 1).once + controller.send("resource_url", :page => 1) + + mock_polymorphic(controller, "news_url").with(news, :page => 1).once + controller.send("parent_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([:arg, new_sheep], {}).once + controller.send("collection_url", :arg) + + controller.expects("polymorphic_url").with([news, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([news, :arg], {}).once + controller.send("edit_resource_url", :arg) + + controller.expects("polymorphic_url").with([:arg], {}).once + controller.send("parent_url", :arg) + end + + def test_url_helpers_on_namespaced_polymorphic_belongs_to + house = House.new + desk = Desk.new + + new_desk = Desk.new + Desk.stubs(:new).returns(new_desk) + new_desk.stubs(:persisted?).returns(false) + + controller = Admin::DesksController.new + controller.instance_variable_set('@parent_type', :house) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@desk', desk) + + [:url, :path].each do |path_or_url| + mock_polymorphic(controller, "admin_house_desks_#{path_or_url}").with(house).once + controller.send("collection_#{path_or_url}") + + mock_polymorphic(controller, "admin_house_desk_#{path_or_url}").with(house, desk).once + controller.send("resource_#{path_or_url}") + + mock_polymorphic(controller, "new_admin_house_desk_#{path_or_url}").with(house).once + controller.send("new_resource_#{path_or_url}") + + mock_polymorphic(controller, "edit_admin_house_desk_#{path_or_url}").with(house, desk).once + controller.send("edit_resource_#{path_or_url}") + + mock_polymorphic(controller, "admin_house_#{path_or_url}").with(house).once + controller.send("parent_#{path_or_url}") + + mock_polymorphic(controller, "edit_admin_house_#{path_or_url}").with(house).once + controller.send("edit_parent_#{path_or_url}") + end + + # With options + mock_polymorphic(controller, "admin_house_desk_url").with(house, desk, :page => 1).once + controller.send("resource_url", :page => 1) + + mock_polymorphic(controller, "admin_house_url").with(house, :page => 1).once + controller.send("parent_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with(['admin', :arg, new_desk], {}).once + controller.send("collection_url", :arg) + + controller.expects("polymorphic_url").with(['admin', house, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with(['admin', house, :arg], {}).once + controller.send("edit_resource_url", :arg) + + controller.expects("polymorphic_url").with(['admin', :arg], {}).once + controller.send("parent_url", :arg) + end + + def test_url_helpers_on_nested_polymorphic_belongs_to + house = House.new + table = Table.new + dish = Dish.new + + new_dish = Dish.new + Dish.stubs(:new).returns(new_dish) + new_dish.stubs(:persisted?).returns(false) + + controller = DishesController.new + controller.instance_variable_set('@parent_type', :table) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@table', table) + controller.instance_variable_set('@dish', dish) + + [:url, :path].each do |path_or_url| + mock_polymorphic(controller, "house_table_dishes_#{path_or_url}").with(house, table).once + controller.send("collection_#{path_or_url}") + + mock_polymorphic(controller, "house_table_dish_#{path_or_url}").with(house, table, dish).once + controller.send("resource_#{path_or_url}") + + mock_polymorphic(controller, "new_house_table_dish_#{path_or_url}").with(house, table).once + controller.send("new_resource_#{path_or_url}") + + mock_polymorphic(controller, "edit_house_table_dish_#{path_or_url}").with(house, table, dish).once + controller.send("edit_resource_#{path_or_url}") + + mock_polymorphic(controller, "house_table_#{path_or_url}").with(house, table).once + controller.send("parent_#{path_or_url}") + + mock_polymorphic(controller, "edit_house_table_#{path_or_url}").with(house, table).once + controller.send("edit_parent_#{path_or_url}") + end + + # With options + mock_polymorphic(controller, "house_table_dish_url").with(house, table, dish, :page => 1).once + controller.send("resource_url", :page => 1) + + mock_polymorphic(controller, "house_table_url").with(house, table, :page => 1).once + controller.send("parent_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([house, table, :arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([house, table, :arg], {}).once + controller.send("edit_resource_url", :arg) + + controller.expects("polymorphic_url").with([house, :arg], {}).once + controller.send("parent_url", :arg) + end + + def test_url_helpers_on_singleton_nested_polymorphic_belongs_to + # This must not be usefull in singleton controllers... + # Center.new + house = House.new + table = Table.new + + controller = CentersController.new + controller.instance_variable_set('@parent_type', :table) + controller.instance_variable_set('@house', house) + controller.instance_variable_set('@table', table) + + # This must not be useful in singleton controllers... + # controller.instance_variable_set('@center', :center) + + [:url, :path].each do |path_or_url| + mock_polymorphic(controller, "house_table_#{path_or_url}").with(house, table).once + controller.send("collection_#{path_or_url}") + + mock_polymorphic(controller, "house_table_center_#{path_or_url}").with(house, table).once + controller.send("resource_#{path_or_url}") + + mock_polymorphic(controller, "new_house_table_center_#{path_or_url}").with(house, table).once + controller.send("new_resource_#{path_or_url}") + + mock_polymorphic(controller, "edit_house_table_center_#{path_or_url}").with(house, table).once + controller.send("edit_resource_#{path_or_url}") + + mock_polymorphic(controller, "house_table_#{path_or_url}").with(house, table).once + controller.send("parent_#{path_or_url}") + + mock_polymorphic(controller, "edit_house_table_#{path_or_url}").with(house, table).once + controller.send("edit_parent_#{path_or_url}") + end + + # With options + mock_polymorphic(controller, "house_table_center_url").with(house, table, :page => 1) + controller.send("resource_url", :page => 1) + + mock_polymorphic(controller, "house_table_url").with(house, table, :page => 1) + controller.send("parent_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([house, table, :center], {}).once + controller.send("resource_url", :arg) + + controller.expects("polymorphic_url").with([house, :arg], {}).once + controller.send("parent_url", :arg) + end + + def test_url_helpers_on_optional_polymorphic_belongs_to + bed = Bed.new + new_bed = Bed.new + Bed.stubs(:new).returns(new_bed) + new_bed.stubs(:persisted?).returns(false) + + controller = BedsController.new + controller.instance_variable_set('@parent_type', nil) + controller.instance_variable_set('@bed', bed) + + [:url, :path].each do |path_or_url| + mock_polymorphic(controller, "beds_#{path_or_url}").with().once + controller.send("collection_#{path_or_url}") + + mock_polymorphic(controller, "bed_#{path_or_url}").with(bed).once + controller.send("resource_#{path_or_url}") + + mock_polymorphic(controller, "new_bed_#{path_or_url}").with().once + controller.send("new_resource_#{path_or_url}") + + mock_polymorphic(controller, "edit_bed_#{path_or_url}").with(bed).once + controller.send("edit_resource_#{path_or_url}") + end + + # With options + mock_polymorphic(controller, "bed_url").with(bed, :page => 1).once + controller.send("resource_url", :page => 1) + + # With args + controller.expects("polymorphic_url").with([:arg], {}).once + controller.send("resource_url", :arg) + + controller.expects("edit_polymorphic_url").with([:arg], {}).once + controller.send("edit_resource_url", :arg) + end + + + def test_url_helpers_on_belongs_to_with_shallowed_route + controller = MirrorsController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@mirror', :mirror) + + [:url, :path].each do |path_or_url| + controller.expects("house_mirrors_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("mirror_#{path_or_url}").with(:mirror, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_house_mirror_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_mirror_#{path_or_url}").with(:mirror, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("house_#{path_or_url}").with(:house, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_parent_#{path_or_url}") + end + end + + def test_url_helpers_on_nested_belongs_to_with_shallowed_route + controller = ButtonsController.new + controller.instance_variable_set('@display', :display) + controller.instance_variable_set('@window', :window) + controller.instance_variable_set('@button', :button) + + [:url, :path].each do |path_or_url| + controller.expects("window_buttons_#{path_or_url}").with(:window, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("button_#{path_or_url}").with(:button, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_window_button_#{path_or_url}").with(:window, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_button_#{path_or_url}").with(:button, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("window_#{path_or_url}").with(:window, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_window_#{path_or_url}").with(:window, {}).once + controller.send("edit_parent_#{path_or_url}") + end + end + + def test_url_helpers_with_custom_actions + controller = ButtonsController.new + controller.instance_variable_set('@display', :display) + controller.instance_variable_set('@window', :window) + controller.instance_variable_set('@button', :button) + [:url, :path].each do |path_or_url| + controller.expects("delete_button_#{path_or_url}").with(:button, {}).once + controller.send("delete_resource_#{path_or_url}") + + controller.expects("search_window_buttons_#{path_or_url}").with(:window, {}).once + controller.send("search_resources_#{path_or_url}") + end + end + + def test_helper_methods_with_custom_actions + controller = ButtonsController.new + helper_methods = controller.class._helpers.instance_methods.map {|m| m.to_s } + [:url, :path].each do |path_or_url| + assert helper_methods.include?("delete_resource_#{path_or_url}") + assert helper_methods.include?("search_resources_#{path_or_url}") + end + end + + def test_helpers_on_inherited_controller + controller = ImageButtonsController.new + controller.expects("edit_image_button_path").once + controller.send("edit_resource_path") + controller.expects("delete_image_button_path").once + controller.send("delete_resource_path") + end + + def test_url_helpers_on_namespaced_resource_with_shallowed_route + controller = Admin::MirrorsController.new + controller.instance_variable_set('@house', :house) + controller.instance_variable_set('@mirror', :mirror) + + [:url, :path].each do |path_or_url| + + controller.expects("admin_house_mirrors_#{path_or_url}").with(:house, {}).once + controller.send("collection_#{path_or_url}") + + controller.expects("admin_mirror_#{path_or_url}").with(:mirror, {}).once + controller.send("resource_#{path_or_url}") + + controller.expects("new_admin_house_mirror_#{path_or_url}").with(:house, {}).once + controller.send("new_resource_#{path_or_url}") + + controller.expects("edit_admin_mirror_#{path_or_url}").with(:mirror, {}).once + controller.send("edit_resource_#{path_or_url}") + + controller.expects("admin_house_#{path_or_url}").with(:house, {}).once + controller.send("parent_#{path_or_url}") + + controller.expects("edit_admin_house_#{path_or_url}").with(:house, {}).once + controller.send("edit_parent_#{path_or_url}") + end + end +end diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cars/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/cities/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/comments/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/educations/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/educations/new.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/employees/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/groups/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/groups/edit.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/managers/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/painters/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/pets/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/plates/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/products/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/professors/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/edit.html.erb new file mode 100644 index 0000000..9221645 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/edit.html.erb @@ -0,0 +1 @@ +Edit HTML \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/index.json.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/index.json.erb new file mode 100644 index 0000000..b220f84 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/index.json.erb @@ -0,0 +1 @@ +Index JSON diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/new.html.erb new file mode 100644 index 0000000..498ec43 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/new.html.erb @@ -0,0 +1 @@ +New HTML \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/respond_to_skip_default_template.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/respond_to_skip_default_template.html.erb new file mode 100644 index 0000000..8e6872d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/respond_to_skip_default_template.html.erb @@ -0,0 +1 @@ +DefaultTemplate HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/respond_with_resource.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/respond_with_resource.html.erb new file mode 100644 index 0000000..c3a2b0b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/respond_with_resource.html.erb @@ -0,0 +1 @@ +RespondTo HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/show.html.erb new file mode 100644 index 0000000..adddaa5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/projects/show.html.erb @@ -0,0 +1 @@ +Show HTML \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/students/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/students/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/students/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/students/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/students/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/students/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/tags/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/trees/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/university/professors/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/create.js.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/create.js.erb new file mode 100644 index 0000000..78b658a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/create.js.erb @@ -0,0 +1 @@ +Create JS \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/destroy.js.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/destroy.js.erb new file mode 100644 index 0000000..5da20c6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/destroy.js.erb @@ -0,0 +1 @@ +Destroy JS \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/edit.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/edit.html.erb new file mode 100644 index 0000000..717208b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/edit.html.erb @@ -0,0 +1 @@ +Edit HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/index.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/index.html.erb new file mode 100644 index 0000000..a8d8731 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/index.html.erb @@ -0,0 +1 @@ +Index HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/new.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/new.html.erb new file mode 100644 index 0000000..6a62138 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/new.html.erb @@ -0,0 +1 @@ +New HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/show.html.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/show.html.erb new file mode 100644 index 0000000..7a5b1dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/show.html.erb @@ -0,0 +1 @@ +Show HTML diff --git a/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/update.js.erb b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/update.js.erb new file mode 100644 index 0000000..654706a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/inherited_resources-1.3.0/test/views/users/update.js.erb @@ -0,0 +1 @@ +Update JS \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/.gitignore b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/.gitignore new file mode 100644 index 0000000..b6a9bbe --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/.gitignore @@ -0,0 +1,7 @@ +pkg/* +tmp +spec/support/*/Gemfile.lock +spec/support/*/public/javascripts +.rvmrc +.bundle +imports/* diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/CHANGELOG.md b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/CHANGELOG.md new file mode 100644 index 0000000..05842e4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/CHANGELOG.md @@ -0,0 +1,182 @@ +## 1.0.19 (26 November 2011) + + - Updated to jQuery 1.7.1 + - Updated to latest jquery-ujs + - Fixed disabled links to re-enable when `ajax:before` or + `ajax:beforeSend` are canceled + - Switched from deprecated `live` to `delegate` + +## 1.0.18 (18 November 2011) + + - Updated to latest jquery-ujs + - Fixed event parameter for form submit event handlers in IE for + jQuery 1.6.x + - Fixed form submit event handlers for jQuery 1.7 + +## 1.0.17 (9 November 2011) + + - Updated to jQuery 1.7 + - Updated to latest jquery-ujs + - Moved file comment above function so it won't be included in + compressed version + +## 1.0.16 (12 October 2011) + + - Updated to jQuery 1.6.4 + - Updated to jQuery UI 1.8.16 + +## 1.0.15 (12 October 2011) + + - Updated to latest jquery-ujs + - Fixed formInputClickSelector `button[type]` for IE7 + - Copy target attribute to generated form for `a[data-method]` links + - Return true (abort ajax) for ctrl- and meta-clicks on remote links + - Use jQuery `.prop()` for disabling/enabling elements + +## 1.0.14 (08 September 2011) + + - Updated to latest jquery-ujs + - Added `disable-with` support for links + - minor bug fixes + - Added `data-remote` support for change events of all input types + - Added install generator for Rails 3.1 with instructional message + +## 1.0.13 (11 August 2011) + + - Updated to latest jquery-ujs with `novalidate` support + - No more support for jquery older than v1.6 + +## 1.0.12 (23 June 2011) + + - Updated to latest jquery-ujs with 'blank form action' and + data-remote support for select elements + +## 1.0.11 (15 June 2011) + + - Updated to latest jqueyr-ujs with cross-domain support + +[See jquery-ujs issue 167](https://github.com/rails/jquery-ujs/pull/167) for relevant discussion + +## 1.0.10 (13 June 2011) + + - Updated to latest jqueyr-ujs with bug fixes + +## 1.0.9 (25 May 2011) + + - Merged with new rails repo (3.1 fix) + +## 1.0.8 (25 May 2011) + + - Updated to latest jquery-ujs with `[disabled][required]` fix + +## 1.0.7 (21 May 2011) + + - Fix assert_select_jquery's bad call to unescape_rjs + +## 1.0.6 (21 May 2011) + + - Updated to latest jquery-ujs with `data-params` support + +## 1.0.5 (17 May 2011) + + - Updated to latest jquery-ujs + - Remove old rails.js in Rails 3.0 generator + +## 1.0.4 (17 May 2011) + + - Fix exception in Rails 3.0 generator + +## 1.0.3 (17 May 2011) + + - Update to jQuery 1.6.1 + - Remove useless --version generator option + +## 1.0.2 (12 May 2011) + + - Fix Rails 3.0 now that rails.js is named jquery_ujs.js + +## 1.0.1 (10 May 2011) + + - Stop downloading rails.js from GitHub + - Vendor jQuery UI for those who want it + - Fix assert_select_jquery now that Rails 3.1 has no RJS at all + - Fix rails dependency to just be railties + +## 1.0.rc (3 May 2011) + + - Rails 3.1 asset pipeline edition + - Removes generators and railties + - Just provides jquery.js and jquery_ujs.js + - Still compatible with Rails 3.0 via the old generator code + +## 0.2.7 (5 February 2011) + + - Updated to use jQuery 1.5 by default + +## 0.2.6 (1 December 2010) + +Feature: + + - Updated to use jQuery 1.4.4 by default + +## 0.2.5 (4 November 2010) + +Bugfix: + + - Download JQuery Rails UJS via HTTPS since Github is now HTTPS only + +## 0.2.4 (16 October 2010) + +Features: + + - Updated to use the new jQuery 1.4.3 by default, with the IE .live() bug fixed + - Always download the newest 1.x release of jQuery UI + - Try to install unknown versions of jQuery, with fallback to the default + - Print informative messages in the correct Generator style + +## 0.2.3 (13 October 2010) + +Features: + + - Support Edge Rails 3.1 by depending on Rails ~>3.0 + - Add Sam Ruby's assert_select_jquery test helper method + - Use jquery.min only in production (and not in the test env) + +## 0.2.2 (8 October 2010) + +Feature: + + - Depend on Rails >=3.0 && <4.0 for edge Rails compatibility + +## 0.2.1 (2 October 2010) + +Bugfix: + + - Default to jQuery 1.4.1 as recommended by jQuery-ujs + due to a bug in 1.4.2 (http://jsbin.com/uboxu3/7/) + +## 0.2 (2 October 2010) + +Features: + + - Allow specifying which version of jQuery to install + - Add generator tests (thanks, Louis T.) + - Automatically use non-minified JS in development mode + +## 0.1.3 (16 September 2010) + +Bugfix: + + - allow javascript :defaults tag to be overridden + +## 0.1.2 (18 August 2010) + +Bugfix: + + - check for jQueryUI in the right place + +## 0.1.1 (16 August 2010) + +Bugfix: + + - fix generator by resolving namespace conflict between Jquery::Rails and ::Rails diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Gemfile b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Gemfile new file mode 100644 index 0000000..ff0992d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Gemfile @@ -0,0 +1,9 @@ +source :gemcutter + +# Specify your gem's dependencies in jquery-rails.gemspec +gemspec +# Rails is already being pulled in through gemspec +# gem "rails", :git => "git://github.com/rails/rails.git" +gem "rack", :git => "git://github.com/rack/rack.git" +gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git" +gem "i18n", "0.6.0beta1" diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Gemfile.lock b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Gemfile.lock new file mode 100644 index 0000000..b958a24 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Gemfile.lock @@ -0,0 +1,100 @@ +GIT + remote: git://github.com/rack/rack.git + revision: a9beb476b27914794743d0677b327d5bafb5e8a3 + specs: + rack (1.2.1) + +GIT + remote: git://github.com/sstephenson/sprockets.git + revision: c4800417792744c11eb1fb888bbe9a3a82859952 + specs: + sprockets (2.0.0.beta.2) + hike (~> 1.0) + rack (~> 1.0) + tilt (~> 1.0) + +PATH + remote: . + specs: + jquery-rails (1.0.17) + railties (~> 3.0) + thor (~> 0.14) + +GEM + remote: http://rubygems.org/ + specs: + abstract (1.0.0) + actionmailer (3.0.5) + actionpack (= 3.0.5) + mail (~> 2.2.15) + actionpack (3.0.5) + activemodel (= 3.0.5) + activesupport (= 3.0.5) + builder (~> 2.1.2) + erubis (~> 2.6.6) + i18n (~> 0.4) + rack (~> 1.2.1) + rack-mount (~> 0.6.13) + rack-test (~> 0.5.7) + tzinfo (~> 0.3.23) + activemodel (3.0.5) + activesupport (= 3.0.5) + builder (~> 2.1.2) + i18n (~> 0.4) + activerecord (3.0.5) + activemodel (= 3.0.5) + activesupport (= 3.0.5) + arel (~> 2.0.2) + tzinfo (~> 0.3.23) + activeresource (3.0.5) + activemodel (= 3.0.5) + activesupport (= 3.0.5) + activesupport (3.0.5) + arel (2.0.10) + builder (2.1.2) + erubis (2.6.6) + abstract (>= 1.0.0) + hike (1.0.0) + i18n (0.6.0beta1) + mail (2.2.19) + activesupport (>= 2.3.6) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.17.2) + polyglot (0.3.3) + rack-mount (0.6.14) + rack (>= 1.0.0) + rack-test (0.5.7) + rack (>= 1.0) + rails (3.0.5) + actionmailer (= 3.0.5) + actionpack (= 3.0.5) + activerecord (= 3.0.5) + activeresource (= 3.0.5) + activesupport (= 3.0.5) + bundler (~> 1.0) + railties (= 3.0.5) + railties (3.0.5) + actionpack (= 3.0.5) + activesupport (= 3.0.5) + rake (>= 0.8.7) + thor (~> 0.14.4) + rake (0.9.2.2) + thor (0.14.6) + tilt (1.3) + treetop (1.4.10) + polyglot + polyglot (>= 0.3.1) + tzinfo (0.3.31) + +PLATFORMS + ruby + +DEPENDENCIES + bundler (~> 1.0.0) + i18n (= 0.6.0beta1) + jquery-rails! + rack! + rails (~> 3.0) + sprockets! diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/LICENSE b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/LICENSE new file mode 100644 index 0000000..d4c1838 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2010 Andre Arko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/README.md b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/README.md new file mode 100644 index 0000000..bab899a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/README.md @@ -0,0 +1,49 @@ +# jquery-rails + +jQuery! For Rails! So great. + +This gem provides: + +* jQuery 1.7.1 +* jQuery UI 1.8.16 +* the latest jQuery UJS adapter +* and Sam Ruby's assert_select_jquery function, which is automatically included for use in tests. + +## Rails 3.1 + +For Rails 3.1 and greater, the files will be added to the asset pipeline and available for you to use. These two lines will be added to the file `app/assets/javascripts/application.js` by default: + + //= require jquery + //= require jquery_ujs + +If you wish to use jQuery UI as well, you can add this line to `application.js`: + + //= require jquery-ui + +In order to use the themed parts of jQuery UI, you will also need to supply your own theme CSS. See [jqueryui.com](http://jqueryui.com) for more information. + +### Installation + +New Rails 3.1 apps include jquery-rails in the Gemfile by default. So just make a new app: + + rails new myapp + +You're done! + +## Rails 3.0 + +This gem adds a single generator to Rails 3, jquery:install. Running the generator will remove any Prototype JS files you may happen to have, fetch jQuery and the jQuery-ujs driver for Rails, and (optionally) fetch jQuery UI. + +The gem will also hook into the Rails configuration process, removing Prototype and adding jQuery to the javascript files included by the `javascript_include_tag(:defaults)` call. While the plugin downloads minified and un-minified versions of jQuery and jQuery UI, only the minified versions are included in :default. + +### Installation + +In your Gemfile, add this line: + + gem "jquery-rails" + +Then, run `bundle install`. To invoke the generator, run: + + rails generate jquery:install #--ui to enable jQuery UI + +You're done! diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Rakefile b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Rakefile new file mode 100644 index 0000000..2209a6a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/Rakefile @@ -0,0 +1,10 @@ +require 'bundler' +Bundler::GemHelper.install_tasks + +# require "spec/rake/spectask" +# desc "Run all examples" +# Spec::Rake::SpecTask.new(:spec) do |t| +# t.ruby_opts = ['-r test/unit'] +# t.spec_opts = %w[--color] +# end +task :default => :spec diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/jquery-rails.gemspec b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/jquery-rails.gemspec new file mode 100644 index 0000000..8a810bc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/jquery-rails.gemspec @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../lib/jquery/rails/version', __FILE__) + +Gem::Specification.new do |s| + s.name = "jquery-rails" + s.version = Jquery::Rails::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["André Arko"] + s.email = ["andre@arko.net"] + s.homepage = "http://rubygems.org/gems/jquery-rails" + s.summary = "Use jQuery with Rails 3" + s.description = "This gem provides jQuery and the jQuery-ujs driver for your Rails 3 application." + + s.required_rubygems_version = ">= 1.3.6" + s.rubyforge_project = "jquery-rails" + + s.add_dependency "railties", "~> 3.0" + s.add_dependency "thor", "~> 0.14" + s.add_development_dependency "bundler", "~> 1.0.0" + s.add_development_dependency "rails", "~> 3.0" + + s.files = `git ls-files`.split("\n") + s.executables = `git ls-files`.split("\n").select{|f| f =~ /^bin/} + s.require_path = 'lib' +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/generators/jquery/install/install_generator.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/generators/jquery/install/install_generator.rb new file mode 100644 index 0000000..f861c2a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/generators/jquery/install/install_generator.rb @@ -0,0 +1,59 @@ +require 'rails' + +# Supply generator for Rails 3.0.x or if asset pipeline is not enabled +if ::Rails.version < "3.1" || !::Rails.application.config.assets.enabled + module Jquery + module Generators + class InstallGenerator < ::Rails::Generators::Base + + desc "This generator installs jQuery #{Jquery::Rails::JQUERY_VERSION}, jQuery-ujs, and (optionally) jQuery UI #{Jquery::Rails::JQUERY_UI_VERSION}" + class_option :ui, :type => :boolean, :default => false, :desc => "Include jQueryUI" + source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__) + + def remove_prototype + Rails::PROTOTYPE_JS.each do |name| + remove_file "public/javascripts/#{name}.js" + end + end + + def copy_jquery + say_status("copying", "jQuery (#{Jquery::Rails::JQUERY_VERSION})", :green) + copy_file "jquery.js", "public/javascripts/jquery.js" + copy_file "jquery.min.js", "public/javascripts/jquery.min.js" + end + + def copy_jquery_ui + if options.ui? + say_status("copying", "jQuery UI (#{Jquery::Rails::JQUERY_UI_VERSION})", :green) + copy_file "jquery-ui.js", "public/javascripts/jquery-ui.js" + copy_file "jquery-ui.min.js", "public/javascripts/jquery-ui.min.js" + end + end + + def copy_ujs_driver + say_status("copying", "jQuery UJS adapter (#{Jquery::Rails::JQUERY_UJS_VERSION[0..5]})", :green) + remove_file "public/javascripts/rails.js" + copy_file "jquery_ujs.js", "public/javascripts/jquery_ujs.js" + end + + end + end + end +else + module Jquery + module Generators + class InstallGenerator < ::Rails::Generators::Base + desc "Just show instructions so people will know what to do when mistakenly using generator for Rails 3.1 apps" + + def do_nothing + say_status("deprecated", "You are using Rails 3.1 with the asset pipeline enabled, so this generator is not needed.") + say_status("", "The necessary files are already in your asset pipeline.") + say_status("", "Just add `//= require jquery` and `//= require jquery_ujs` to your app/assets/javascripts/application.js") + say_status("", "If you upgraded your app from Rails 3.0 and still have jquery.js, rails.js, or jquery_ujs.js in your javascripts, be sure to remove them.") + say_status("", "If you do not want the asset pipeline enabled, you may turn it off in application.rb and re-run this generator.") + # ok, nothing + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery-rails.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery-rails.rb new file mode 100644 index 0000000..a0fcf9a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery-rails.rb @@ -0,0 +1 @@ +require 'jquery/rails' \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/assert_select.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/assert_select.rb new file mode 100644 index 0000000..7cdf8fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/assert_select.rb @@ -0,0 +1,99 @@ +module ActionDispatch + module Assertions + module SelectorAssertions + # Selects content from a JQuery response. Patterned loosely on + # assert_select_rjs. + # + # === Narrowing down + # + # With no arguments, asserts that one or more method calls are made. + # + # Use the +method+ argument to narrow down the assertion to only + # statements that call that specific method. + # + # Use the +opt+ argument to narrow down the assertion to only statements + # that pass +opt+ as the first argument. + # + # Use the +id+ argument to narrow down the assertion to only statements + # that invoke methods on the result of using that identifier as a + # selector. + # + # === Using blocks + # + # Without a block, +assert_select_jquery_ merely asserts that the + # response contains one or more statements that match the conditions + # specified above + # + # With a block +assert_select_jquery_ also asserts that the method call + # passes a javascript escaped string containing HTML. All such HTML + # fragments are selected and passed to the block. Nested assertions are + # supported. + # + # === Examples + # + # # asserts that the #notice element is hidden + # assert_select :hide, '#notice' + # + # # asserts that the #cart element is shown with a blind parameter + # assert_select :show, :blind, '#cart' + # + # # asserts that #cart content contains a #current_item + # assert_select :html, '#cart' do + # assert_select '#current_item' + # end + + PATTERN_HTML = "\"((\\\\\"|[^\"])*)\"" + PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/ + + def assert_select_jquery(*args, &block) + jquery_method = args.first.is_a?(Symbol) ? args.shift : nil + jquery_opt = args.first.is_a?(Symbol) ? args.shift : nil + id = args.first.is_a?(String) ? args.shift : nil + + pattern = "\\.#{jquery_method || '\\w+'}\\(" + pattern = "#{pattern}['\"]#{jquery_opt}['\"],?\\s*" if jquery_opt + pattern = "#{pattern}#{PATTERN_HTML}" + pattern = "(?:jQuery|\\$)\\(['\"]#{id}['\"]\\)#{pattern}" if id + + fragments = [] + response.body.scan(Regexp.new(pattern)).each do |match| + doc = HTML::Document.new(unescape_js(match.first)) + doc.root.children.each do |child| + fragments.push child if child.tag? + end + end + + if fragments.empty? + opts = [jquery_method, jquery_opt, id].compact + flunk "No JQuery call matches #{opts.inspect}" + end + + if block + begin + in_scope, @selected = @selected, fragments + yield + ensure + @selected = in_scope + end + end + end + + private + + # Unescapes a JS string. + def unescape_js(js_string) + # js encodes double quotes and line breaks. + unescaped= js_string.gsub('\"', '"') + unescaped.gsub!('\\\'', "'") + unescaped.gsub!(/\\\//, '/') + unescaped.gsub!('\n', "\n") + unescaped.gsub!('\076', '>') + unescaped.gsub!('\074', '<') + # js encodes non-ascii characters. + unescaped.gsub!(PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')} + unescaped + end + + end + end +end diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails.rb new file mode 100644 index 0000000..15beb50 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails.rb @@ -0,0 +1,12 @@ +module Jquery + module Rails + PROTOTYPE_JS = %w{prototype effects dragdrop controls} + + if ::Rails.version < "3.1" + require 'jquery/rails/railtie' + else + require 'jquery/rails/engine' + end + require 'jquery/rails/version' + end +end diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/engine.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/engine.rb new file mode 100644 index 0000000..ee6139b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/engine.rb @@ -0,0 +1,12 @@ +# Configure Rails 3.1 to have assert_select_jquery() in tests +module Jquery + module Rails + + class Engine < ::Rails::Engine + config.before_configuration do + require "jquery/assert_select" if ::Rails.env.test? + end + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/railtie.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/railtie.rb new file mode 100644 index 0000000..1b03474 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/railtie.rb @@ -0,0 +1,25 @@ +# Configure Rails 3.0 to use public/javascripts/jquery et al +module Jquery + module Rails + + class Railtie < ::Rails::Railtie + config.before_configuration do + require "jquery/assert_select" if ::Rails.env.test? + + if ::Rails.root.join("public/javascripts/jquery-ui.min.js").exist? + jq_defaults = %w(jquery jquery-ui) + jq_defaults.map!{|a| a + ".min" } if ::Rails.env.production? + else + jq_defaults = ::Rails.env.production? ? %w(jquery.min) : %w(jquery) + end + + # Merge the jQuery scripts, remove the Prototype defaults and finally add 'jquery_ujs' + # at the end, because load order is important + config.action_view.javascript_expansions[:defaults] -= PROTOTYPE_JS + ['rails'] + config.action_view.javascript_expansions[:defaults] |= jq_defaults + config.action_view.javascript_expansions[:defaults] << 'jquery_ujs' + end + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/version.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/version.rb new file mode 100644 index 0000000..2a2b0d8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/lib/jquery/rails/version.rb @@ -0,0 +1,8 @@ +module Jquery + module Rails + VERSION = "1.0.19" + JQUERY_VERSION = "1.7.1" + JQUERY_UI_VERSION = "1.8.16" + JQUERY_UJS_VERSION = "82292010fb1743f038ab72b1f1e994e91be3eda3" + end +end diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/spec/lib/jquery-rails_spec.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/spec/lib/jquery-rails_spec.rb new file mode 100644 index 0000000..889bf86 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/spec/lib/jquery-rails_spec.rb @@ -0,0 +1,3 @@ +require 'spec_helper' + +it "should probably test something, but I'm damned if I know what" \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/spec/spec_helper.rb b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/spec/spec_helper.rb new file mode 100644 index 0000000..4554297 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/spec/spec_helper.rb @@ -0,0 +1,29 @@ +# Set up RSpec +require 'webmock/rspec' + +Spec::Runner.configure do |config| + config.include WebMock::API +end + +# Set up generator tests +require 'rails/all' +require 'rails/generators' +require 'rails/generators/test_case' + +class TestApp < Rails::Application + config.root = File.dirname(__FILE__) +end +Rails.application = TestApp + +module Rails + def self.root + @root ||= File.expand_path("../../tmp/rails", __FILE__) + end +end +Rails.application.config.root = Rails.root + +# Call configure to load the settings from +# Rails.application.config.generators to Rails::Generators +Rails::Generators.configure! + + diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery-ui.js b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery-ui.js new file mode 100644 index 0000000..fc8d9d1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery-ui.js @@ -0,0 +1,11767 @@ +/*! + * jQuery UI 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function( $, undefined ) { + +// prevent duplicate loading +// this is only a problem because we proxy existing functions +// and we don't want to double proxy them +$.ui = $.ui || {}; +if ( $.ui.version ) { + return; +} + +$.extend( $.ui, { + version: "1.8.16", + + keyCode: { + ALT: 18, + BACKSPACE: 8, + CAPS_LOCK: 20, + COMMA: 188, + COMMAND: 91, + COMMAND_LEFT: 91, // COMMAND + COMMAND_RIGHT: 93, + CONTROL: 17, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + INSERT: 45, + LEFT: 37, + MENU: 93, // COMMAND_RIGHT + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SHIFT: 16, + SPACE: 32, + TAB: 9, + UP: 38, + WINDOWS: 91 // COMMAND + } +}); + +// plugins +$.fn.extend({ + propAttr: $.fn.prop || $.fn.attr, + + _focus: $.fn.focus, + focus: function( delay, fn ) { + return typeof delay === "number" ? + this.each(function() { + var elem = this; + setTimeout(function() { + $( elem ).focus(); + if ( fn ) { + fn.call( elem ); + } + }, delay ); + }) : + this._focus.apply( this, arguments ); + }, + + scrollParent: function() { + var scrollParent; + if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } + + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; + }, + + zIndex: function( zIndex ) { + if ( zIndex !== undefined ) { + return this.css( "zIndex", zIndex ); + } + + if ( this.length ) { + var elem = $( this[ 0 ] ), position, value; + while ( elem.length && elem[ 0 ] !== document ) { + // Ignore z-index if position is set to a value where z-index is ignored by the browser + // This makes behavior of this function consistent across browsers + // WebKit always returns auto if the element is positioned + position = elem.css( "position" ); + if ( position === "absolute" || position === "relative" || position === "fixed" ) { + // IE returns 0 when zIndex is not specified + // other browsers return a string + // we ignore the case of nested elements with an explicit value of 0 + //
                        + value = parseInt( elem.css( "zIndex" ), 10 ); + if ( !isNaN( value ) && value !== 0 ) { + return value; + } + } + elem = elem.parent(); + } + } + + return 0; + }, + + disableSelection: function() { + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + + ".ui-disableSelection", function( event ) { + event.preventDefault(); + }); + }, + + enableSelection: function() { + return this.unbind( ".ui-disableSelection" ); + } +}); + +$.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; + if ( border ) { + size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; + } + }); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each(function() { + $( this ).css( type, reduce( this, size ) + "px" ); + }); + }; + + $.fn[ "outer" + name] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each(function() { + $( this).css( type, reduce( this, size, true, margin ) + "px" ); + }); + }; +}); + +// selectors +function focusable( element, isTabIndexNotNaN ) { + var nodeName = element.nodeName.toLowerCase(); + if ( "area" === nodeName ) { + var map = element.parentNode, + mapName = map.name, + img; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap=#" + mapName + "]" )[0]; + return !!img && visible( img ); + } + return ( /input|select|textarea|button|object/.test( nodeName ) + ? !element.disabled + : "a" == nodeName + ? element.href || isTabIndexNotNaN + : isTabIndexNotNaN) + // the element and all of its ancestors must be visible + && visible( element ); +} + +function visible( element ) { + return !$( element ).parents().andSelf().filter(function() { + return $.curCSS( this, "visibility" ) === "hidden" || + $.expr.filters.hidden( this ); + }).length; +} + +$.extend( $.expr[ ":" ], { + data: function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + }, + + focusable: function( element ) { + return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); + }, + + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + isTabIndexNaN = isNaN( tabIndex ); + return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); + } +}); + +// support +$(function() { + var body = document.body, + div = body.appendChild( div = document.createElement( "div" ) ); + + $.extend( div.style, { + minHeight: "100px", + height: "auto", + padding: 0, + borderWidth: 0 + }); + + $.support.minHeight = div.offsetHeight === 100; + $.support.selectstart = "onselectstart" in div; + + // set display to none to avoid a layout bug in IE + // http://dev.jquery.com/ticket/4014 + body.removeChild( div ).style.display = "none"; +}); + + + + + +// deprecated +$.extend( $.ui, { + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function( module, option, set ) { + var proto = $.ui[ module ].prototype; + for ( var i in set ) { + proto.plugins[ i ] = proto.plugins[ i ] || []; + proto.plugins[ i ].push( [ option, set[ i ] ] ); + } + }, + call: function( instance, name, args ) { + var set = instance.plugins[ name ]; + if ( !set || !instance.element[ 0 ].parentNode ) { + return; + } + + for ( var i = 0; i < set.length; i++ ) { + if ( instance.options[ set[ i ][ 0 ] ] ) { + set[ i ][ 1 ].apply( instance.element, args ); + } + } + } + }, + + // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() + contains: function( a, b ) { + return document.compareDocumentPosition ? + a.compareDocumentPosition( b ) & 16 : + a !== b && a.contains( b ); + }, + + // only used by resizable + hasScroll: function( el, a ) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ( $( el ).css( "overflow" ) === "hidden") { + return false; + } + + var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", + has = false; + + if ( el[ scroll ] > 0 ) { + return true; + } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[ scroll ] = 1; + has = ( el[ scroll ] > 0 ); + el[ scroll ] = 0; + return has; + }, + + // these are odd functions, fix the API or move into individual plugins + isOverAxis: function( x, reference, size ) { + //Determines when x coordinate is over "b" element axis + return ( x > reference ) && ( x < ( reference + size ) ); + }, + isOver: function( y, x, top, left, height, width ) { + //Determines when x, y coordinates is over "b" element + return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); + } +}); + +})( jQuery ); +/*! + * jQuery UI Widget 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function( $, undefined ) { + +// jQuery 1.4+ +if ( $.cleanData ) { + var _cleanData = $.cleanData; + $.cleanData = function( elems ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + try { + $( elem ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + } + _cleanData( elems ); + }; +} else { + var _remove = $.fn.remove; + $.fn.remove = function( selector, keepData ) { + return this.each(function() { + if ( !keepData ) { + if ( !selector || $.filter( selector, [ this ] ).length ) { + $( "*", this ).add( [ this ] ).each(function() { + try { + $( this ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + }); + } + } + return _remove.call( $(this), selector, keepData ); + }); + }; +} + +$.widget = function( name, base, prototype ) { + var namespace = name.split( "." )[ 0 ], + fullName; + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName ] = function( elem ) { + return !!$.data( elem, name ); + }; + + $[ namespace ] = $[ namespace ] || {}; + $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + var basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from +// $.each( basePrototype, function( key, val ) { +// if ( $.isPlainObject(val) ) { +// basePrototype[ key ] = $.extend( {}, val ); +// } +// }); + basePrototype.options = $.extend( true, {}, basePrototype.options ); + $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { + namespace: namespace, + widgetName: name, + widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, + widgetBaseClass: fullName + }, prototype ); + + $.widget.bridge( name, $[ namespace ][ name ] ); +}; + +$.widget.bridge = function( name, object ) { + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = Array.prototype.slice.call( arguments, 1 ), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.extend.apply( null, [ true, options ].concat(args) ) : + options; + + // prevent calls to internal methods + if ( isMethodCall && options.charAt( 0 ) === "_" ) { + return returnValue; + } + + if ( isMethodCall ) { + this.each(function() { + var instance = $.data( this, name ), + methodValue = instance && $.isFunction( instance[options] ) ? + instance[ options ].apply( instance, args ) : + instance; + // TODO: add this back in 1.9 and use $.error() (see #5972) +// if ( !instance ) { +// throw "cannot call methods on " + name + " prior to initialization; " + +// "attempted to call method '" + options + "'"; +// } +// if ( !$.isFunction( instance[options] ) ) { +// throw "no such method '" + options + "' for " + name + " widget instance"; +// } +// var methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue; + return false; + } + }); + } else { + this.each(function() { + var instance = $.data( this, name ); + if ( instance ) { + instance.option( options || {} )._init(); + } else { + $.data( this, name, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } +}; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + options: { + disabled: false + }, + _createWidget: function( options, element ) { + // $.widget.bridge stores the plugin instance, but we do it anyway + // so that it's stored even before the _create function runs + $.data( element, this.widgetName, this ); + this.element = $( element ); + this.options = $.extend( true, {}, + this.options, + this._getCreateOptions(), + options ); + + var self = this; + this.element.bind( "remove." + this.widgetName, function() { + self.destroy(); + }); + + this._create(); + this._trigger( "create" ); + this._init(); + }, + _getCreateOptions: function() { + return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; + }, + _create: function() {}, + _init: function() {}, + + destroy: function() { + this.element + .unbind( "." + this.widgetName ) + .removeData( this.widgetName ); + this.widget() + .unbind( "." + this.widgetName ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetBaseClass + "-disabled " + + "ui-state-disabled" ); + }, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.extend( {}, this.options ); + } + + if (typeof key === "string" ) { + if ( value === undefined ) { + return this.options[ key ]; + } + options = {}; + options[ key ] = value; + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var self = this; + $.each( options, function( key, value ) { + self._setOption( key, value ); + }); + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + [ value ? "addClass" : "removeClass"]( + this.widgetBaseClass + "-disabled" + " " + + "ui-state-disabled" ) + .attr( "aria-disabled", value ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _trigger: function( type, event, data ) { + var callback = this.options[ type ]; + + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + data = data || {}; + + // copy original event properties over to the new event + // this would happen if we could call $.event.fix instead of $.Event + // but we don't have a way to force an event to be fixed multiple times + if ( event.originalEvent ) { + for ( var i = $.event.props.length, prop; i; ) { + prop = $.event.props[ --i ]; + event[ prop ] = event.originalEvent[ prop ]; + } + } + + this.element.trigger( event, data ); + + return !( $.isFunction(callback) && + callback.call( this.element[0], event, data ) === false || + event.isDefaultPrevented() ); + } +}; + +})( jQuery ); +/*! + * jQuery UI Mouse 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var mouseHandled = false; +$( document ).mouseup( function( e ) { + mouseHandled = false; +}); + +$.widget("ui.mouse", { + options: { + cancel: ':input,option', + distance: 1, + delay: 0 + }, + _mouseInit: function() { + var self = this; + + this.element + .bind('mousedown.'+this.widgetName, function(event) { + return self._mouseDown(event); + }) + .bind('click.'+this.widgetName, function(event) { + if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { + $.removeData(event.target, self.widgetName + '.preventClickEvent'); + event.stopImmediatePropagation(); + return false; + } + }); + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind('.'+this.widgetName); + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + if( mouseHandled ) { return }; + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var self = this, + btnIsLeft = (event.which == 1), + // event.target.nodeName works around a bug in IE 8 with + // disabled inputs (#7620) + elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + self.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // Click event may never have fired (Gecko & Opera) + if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { + $.removeData(event.target, this.widgetName + '.preventClickEvent'); + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return self._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return self._mouseUp(event); + }; + $(document) + .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + event.preventDefault(); + + mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + + if (event.target == this._mouseDownEvent.target) { + $.data(event.target, this.widgetName + '.preventClickEvent', true); + } + + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(event) {}, + _mouseDrag: function(event) {}, + _mouseStop: function(event) {}, + _mouseCapture: function(event) { return true; } +}); + +})(jQuery); +/* + * jQuery UI Position 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */ +(function( $, undefined ) { + +$.ui = $.ui || {}; + +var horizontalPositions = /left|center|right/, + verticalPositions = /top|center|bottom/, + center = "center", + _position = $.fn.position, + _offset = $.fn.offset; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var target = $( options.of ), + targetElem = target[0], + collision = ( options.collision || "flip" ).split( " " ), + offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], + targetWidth, + targetHeight, + basePosition; + + if ( targetElem.nodeType === 9 ) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top: 0, left: 0 }; + // TODO: use $.isWindow() in 1.9 + } else if ( targetElem.setTimeout ) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; + } else if ( targetElem.preventDefault ) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + basePosition = { top: options.of.pageY, left: options.of.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + basePosition = target.offset(); + } + + // force my and at to have valid horizontal and veritcal positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[this] || "" ).split( " " ); + if ( pos.length === 1) { + pos = horizontalPositions.test( pos[0] ) ? + pos.concat( [center] ) : + verticalPositions.test( pos[0] ) ? + [ center ].concat( pos ) : + [ center, center ]; + } + pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; + pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; + options[ this ] = pos; + }); + + // normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + // normalize offset option + offset[ 0 ] = parseInt( offset[0], 10 ) || 0; + if ( offset.length === 1 ) { + offset[ 1 ] = offset[ 0 ]; + } + offset[ 1 ] = parseInt( offset[1], 10 ) || 0; + + if ( options.at[0] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[0] === center ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[1] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[1] === center ) { + basePosition.top += targetHeight / 2; + } + + basePosition.left += offset[ 0 ]; + basePosition.top += offset[ 1 ]; + + return this.each(function() { + var elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, + marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, + collisionWidth = elemWidth + marginLeft + + ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), + collisionHeight = elemHeight + marginTop + + ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), + position = $.extend( {}, basePosition ), + collisionPosition; + + if ( options.my[0] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[0] === center ) { + position.left -= elemWidth / 2; + } + + if ( options.my[1] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[1] === center ) { + position.top -= elemHeight / 2; + } + + // prevent fractions (see #5280) + position.left = Math.round( position.left ); + position.top = Math.round( position.top ); + + collisionPosition = { + left: position.left - marginLeft, + top: position.top - marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[i] ] ) { + $.ui.position[ collision[i] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: offset, + my: options.my, + at: options.at + }); + } + }); + + if ( $.fn.bgiframe ) { + elem.bgiframe(); + } + elem.offset( $.extend( position, { using: options.using } ) ); + }); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var win = $( window ), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); + position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); + }, + top: function( position, data ) { + var win = $( window ), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); + position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); + } + }, + + flip: { + left: function( position, data ) { + if ( data.at[0] === center ) { + return; + } + var win = $( window ), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + -data.targetWidth, + offset = -2 * data.offset[ 0 ]; + position.left += data.collisionPosition.left < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + }, + top: function( position, data ) { + if ( data.at[1] === center ) { + return; + } + var win = $( window ), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), + myOffset = data.my[ 1 ] === "top" ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + -data.targetHeight, + offset = -2 * data.offset[ 1 ]; + position.top += data.collisionPosition.top < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + } + } +}; + +// offset setter from jQuery 1.4 +if ( !$.offset.setOffset ) { + $.offset.setOffset = function( elem, options ) { + // set position first, in-case top/left are set even on static elem + if ( /static/.test( $.curCSS( elem, "position" ) ) ) { + elem.style.position = "relative"; + } + var curElem = $( elem ), + curOffset = curElem.offset(), + curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, + curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, + props = { + top: (options.top - curOffset.top) + curTop, + left: (options.left - curOffset.left) + curLeft + }; + + if ( 'using' in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + }; + + $.fn.offset = function( options ) { + var elem = this[ 0 ]; + if ( !elem || !elem.ownerDocument ) { return null; } + if ( options ) { + return this.each(function() { + $.offset.setOffset( this, options ); + }); + } + return _offset.call( this ); + }; +} + +}( jQuery )); +/* + * jQuery UI Draggable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.draggable", $.ui.mouse, { + widgetEventPrefix: "drag", + options: { + addClasses: true, + appendTo: "parent", + axis: false, + connectToSortable: false, + containment: false, + cursor: "auto", + cursorAt: false, + grid: false, + handle: false, + helper: "original", + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scope: "default", + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false + }, + _create: function() { + + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; + + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); + + this._mouseInit(); + + }, + + destroy: function() { + if(!this.element.data('draggable')) return; + this.element + .removeData("draggable") + .unbind(".draggable") + .removeClass("ui-draggable" + + " ui-draggable-dragging" + + " ui-draggable-disabled"); + this._mouseDestroy(); + + return this; + }, + + _mouseCapture: function(event) { + + var o = this.options; + + // among others, prevent a drag on a resizable-handle + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; + + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; + + if ( o.iframeFix ) { + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $('
                        ') + .css({ + width: this.offsetWidth+"px", height: this.offsetHeight+"px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + } + + return true; + + }, + + _mouseStart: function(event) { + + var o = this.options; + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + //If ddmanager is used for droppables, set the global draggable + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.positionAbs = this.element.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this.position = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + //Trigger event + callbacks + if(this._trigger("start", event) === false) { + this._clear(); + return false; + } + + //Recache the helper size + this._cacheHelperProportions(); + + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.helper.addClass("ui-draggable-dragging"); + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) + if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); + + return true; + }, + + _mouseDrag: function(event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + if(this._trigger('drag', event, ui) === false) { + this._mouseUp({}); + return false; + } + this.position = ui.position; + } + + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if(this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + //if the original element is removed, don't bother to continue if helper is set to "original" + if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original") + return false; + + if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var self = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + if(self._trigger("stop", event) !== false) { + self._clear(); + } + }); + } else { + if(this._trigger("stop", event) !== false) { + this._clear(); + } + } + + return false; + }, + + _mouseUp: function(event) { + if (this.options.iframeFix === true) { + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); + }); //Remove frame helpers + } + + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) + if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); + + return $.ui.mouse.prototype._mouseUp.call(this, event); + }, + + cancel: function() { + + if(this.helper.is(".ui-draggable-dragging")) { + this._mouseUp({}); + } else { + this._clear(); + } + + return this; + + }, + + _getHandle: function(event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function() { + if(this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); + + if(!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"),10) || 0), + top: (parseInt(this.element.css("marginTop"),10) || 0), + right: (parseInt(this.element.css("marginRight"),10) || 0), + bottom: (parseInt(this.element.css("marginBottom"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, + (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var c = $(o.containment); + var ce = c[0]; if(!ce) return; + var co = c.offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), + (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, + (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom + ]; + this.relative_container = c; + + } else if(o.containment.constructor == Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + var containment; + if(this.containment) { + if (this.relative_container){ + var co = this.relative_container.offset(); + containment = [ this.containment[0] + co.left, + this.containment[1] + co.top, + this.containment[2] + co.left, + this.containment[3] + co.top ]; + } + else { + containment = this.containment; + } + + if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; + } + + if(o.grid) { + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; + pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; + pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins: {}, + + _uiHash: function(event) { + return { + helper: this.helper, + position: this.position, + originalPosition: this.originalPosition, + offset: this.positionAbs + }; + } + +}); + +$.extend($.ui.draggable, { + version: "1.8.16" +}); + +$.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop: function(event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); + + $.each(inst.sortables, function() { + if(this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if(this.shouldRevert) this.instance.options.revert = true; + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if(inst.options.helper == 'original') + this.instance.currentItem.css({ top: 'auto', left: 'auto' }); + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), self = this; + + var checkPos = function(o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; + + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; + + $.each(inst.sortables, function(i) { + + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if(this.instance._intersectsWith(this.instance.containerCache)) { + + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if(!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { return ui.helper[0]; }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if(this.instance.currentItem) this.instance._mouseDrag(event); + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if(this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if(this.instance.placeholder) this.instance.placeholder.remove(); + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + }; + + }); + + } +}); + +$.ui.plugin.add("draggable", "cursor", { + start: function(event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } +}); + +$.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if(t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if(o._opacity) $(ui.helper).css('opacity', o._opacity); + } +}); + +$.ui.plugin.add("draggable", "scroll", { + start: function(event, ui) { + var i = $(this).data("draggable"); + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options, scrolled = false; + + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + + if(!o.axis || o.axis != 'x') { + if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if(!o.axis || o.axis != 'y') { + if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if(!o.axis || o.axis != 'x') { + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if(!o.axis || o.axis != 'y') { + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); + + } +}); + +$.ui.plugin.add("draggable", "snap", { + start: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + var $t = $(this); var $o = $t.offset(); + if(this != i.element[0]) i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; + + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (var i = inst.snapElements.length - 1; i >= 0; i--){ + + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { + if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if(o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if(o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + + if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + }; + + } +}); + +$.ui.plugin.add("draggable", "stack", { + start: function(event, ui) { + + var o = $(this).data("draggable").options; + + var group = $.makeArray($(o.stack)).sort(function(a,b) { + return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); + }); + if (!group.length) { return; } + + var min = parseInt(group[0].style.zIndex) || 0; + $(group).each(function(i) { + this.style.zIndex = min + i; + }); + + this[0].style.zIndex = min + group.length; + + } +}); + +$.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if(t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("draggable").options; + if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } +}); + +})(jQuery); +/* + * jQuery UI Droppable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Droppables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js + */ +(function( $, undefined ) { + +$.widget("ui.droppable", { + widgetEventPrefix: "drop", + options: { + accept: '*', + activeClass: false, + addClasses: true, + greedy: false, + hoverClass: false, + scope: 'default', + tolerance: 'intersect' + }, + _create: function() { + + var o = this.options, accept = o.accept; + this.isover = 0; this.isout = 1; + + this.accept = $.isFunction(accept) ? accept : function(d) { + return d.is(accept); + }; + + //Store the droppable's proportions + this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; + + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; + $.ui.ddmanager.droppables[o.scope].push(this); + + (o.addClasses && this.element.addClass("ui-droppable")); + + }, + + destroy: function() { + var drop = $.ui.ddmanager.droppables[this.options.scope]; + for ( var i = 0; i < drop.length; i++ ) + if ( drop[i] == this ) + drop.splice(i, 1); + + this.element + .removeClass("ui-droppable ui-droppable-disabled") + .removeData("droppable") + .unbind(".droppable"); + + return this; + }, + + _setOption: function(key, value) { + + if(key == 'accept') { + this.accept = $.isFunction(value) ? value : function(d) { + return d.is(value); + }; + } + $.Widget.prototype._setOption.apply(this, arguments); + }, + + _activate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.addClass(this.options.activeClass); + (draggable && this._trigger('activate', event, this.ui(draggable))); + }, + + _deactivate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + (draggable && this._trigger('deactivate', event, this.ui(draggable))); + }, + + _over: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); + this._trigger('over', event, this.ui(draggable)); + } + + }, + + _out: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('out', event, this.ui(draggable)); + } + + }, + + _drop: function(event,custom) { + + var draggable = custom || $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element + + var childrenIntersection = false; + this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, 'droppable'); + if( + inst.options.greedy + && !inst.options.disabled + && inst.options.scope == draggable.options.scope + && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) + && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) + ) { childrenIntersection = true; return false; } + }); + if(childrenIntersection) return false; + + if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('drop', event, this.ui(draggable)); + return this.element; + } + + return false; + + }, + + ui: function(c) { + return { + draggable: (c.currentItem || c.element), + helper: c.helper, + position: c.position, + offset: c.positionAbs + }; + } + +}); + +$.extend($.ui.droppable, { + version: "1.8.16" +}); + +$.ui.intersect = function(draggable, droppable, toleranceMode) { + + if (!droppable.offset) return false; + + var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; + var l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; + + switch (toleranceMode) { + case 'fit': + return (l <= x1 && x2 <= r + && t <= y1 && y2 <= b); + break; + case 'intersect': + return (l < x1 + (draggable.helperProportions.width / 2) // Right Half + && x2 - (draggable.helperProportions.width / 2) < r // Left Half + && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half + && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + break; + case 'pointer': + var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), + isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); + return isOver; + break; + case 'touch': + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + break; + default: + return false; + break; + } + +}; + +/* + This manager tracks offsets of draggables and droppables +*/ +$.ui.ddmanager = { + current: null, + droppables: { 'default': [] }, + prepareOffsets: function(t, event) { + + var m = $.ui.ddmanager.droppables[t.options.scope] || []; + var type = event ? event.type : null; // workaround for #2317 + var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + + droppablesLoop: for (var i = 0; i < m.length; i++) { + + if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted + for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item + m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue + + if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables + + m[i].offset = m[i].element.offset(); + m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; + + } + + }, + drop: function(draggable, event) { + + var dropped = false; + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(!this.options) return; + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) + dropped = dropped || this._drop.call(this, event); + + if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + this.isout = 1; this.isover = 0; + this._deactivate.call(this, event); + } + + }); + return dropped; + + }, + dragStart: function( draggable, event ) { + //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) + draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + }); + }, + drag: function(draggable, event) { + + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + + //Run through all droppables and check their positions based on specific tolerance options + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(this.options.disabled || this.greedyChild || !this.visible) return; + var intersects = $.ui.intersect(draggable, this, this.options.tolerance); + + var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); + if(!c) return; + + var parentInstance; + if (this.options.greedy) { + var parent = this.element.parents(':data(droppable):eq(0)'); + if (parent.length) { + parentInstance = $.data(parent[0], 'droppable'); + parentInstance.greedyChild = (c == 'isover' ? 1 : 0); + } + } + + // we just moved into a greedy child + if (parentInstance && c == 'isover') { + parentInstance['isover'] = 0; + parentInstance['isout'] = 1; + parentInstance._out.call(parentInstance, event); + } + + this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; + this[c == "isover" ? "_over" : "_out"].call(this, event); + + // we just moved out of a greedy child + if (parentInstance && c == 'isout') { + parentInstance['isout'] = 0; + parentInstance['isover'] = 1; + parentInstance._over.call(parentInstance, event); + } + }); + + }, + dragStop: function( draggable, event ) { + draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); + //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + } +}; + +})(jQuery); +/* + * jQuery UI Resizable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.resizable", $.ui.mouse, { + widgetEventPrefix: "resize", + options: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + containment: false, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + zIndex: 1000 + }, + _create: function() { + + var self = this, o = this.options; + this.element.addClass("ui-resizable"); + + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null + }); + + //Wrap the element if it cannot hold child nodes + if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { + + //Opera fix for relative positioning + if (/relative/.test(this.element.css('position')) && $.browser.opera) + this.element.css({ position: 'relative', top: 'auto', left: 'auto' }); + + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $('
                        ').css({ + position: this.element.css('position'), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css('top'), + left: this.element.css('left') + }) + ); + + //Overwrite the original this.element + this.element = this.element.parent().data( + "resizable", this.element.data('resizable') + ); + + this.elementIsWrapper = true; + + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); + + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css('resize'); + this.originalElement.css('resize', 'none'); + + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); + + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css('margin') }); + + // fix handlers offset + this._proportionallyResize(); + + } + + this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); + if(this.handles.constructor == String) { + + if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; + var n = this.handles.split(","); this.handles = {}; + + for(var i = 0; i < n.length; i++) { + + var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; + var axis = $('
                        '); + + // increase zIndex of sw, se, ne, nw axis + //TODO : this modifies original option + if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); + + //TODO : What's going on here? + if ('se' == handle) { + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); + }; + + //Insert into internal handles object and append to element + this.handles[handle] = '.ui-resizable-'+handle; + this.element.append(axis); + } + + } + + this._renderAxis = function(target) { + + target = target || this.element; + + for(var i in this.handles) { + + if(this.handles[i].constructor == String) + this.handles[i] = $(this.handles[i], this.element).show(); + + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + + var axis = $(this.handles[i], this.element), padWrapper = 0; + + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + + //The padding type i have to apply... + var padPos = [ 'padding', + /ne|nw|n/.test(i) ? 'Top' : + /se|sw|s/.test(i) ? 'Bottom' : + /^e$/.test(i) ? 'Right' : 'Left' ].join(""); + + target.css(padPos, padWrapper); + + this._proportionallyResize(); + + } + + //TODO: What's that good for? There's not anything to be executed left + if(!$(this.handles[i]).length) + continue; + + } + }; + + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); + + this._handles = $('.ui-resizable-handle', this.element) + .disableSelection(); + + //Matching axis name + this._handles.mouseover(function() { + if (!self.resizing) { + if (this.className) + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + //Axis, default = se + self.axis = axis && axis[1] ? axis[1] : 'se'; + } + }); + + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .hover(function() { + if (o.disabled) return; + $(this).removeClass("ui-resizable-autohide"); + self._handles.show(); + }, + function(){ + if (o.disabled) return; + if (!self.resizing) { + $(this).addClass("ui-resizable-autohide"); + self._handles.hide(); + } + }); + } + + //Initialize the mouse interaction + this._mouseInit(); + + }, + + destroy: function() { + + this._mouseDestroy(); + + var _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); + }; + + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + var wrapper = this.element; + wrapper.after( + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }) + ).remove(); + } + + this.originalElement.css('resize', this.originalResizeStyle); + _destroy(this.originalElement); + + return this; + }, + + _mouseCapture: function(event) { + var handle = false; + for (var i in this.handles) { + if ($(this.handles[i])[0] == event.target) { + handle = true; + } + } + + return !this.options.disabled && handle; + }, + + _mouseStart: function(event) { + + var o = this.options, iniPos = this.element.position(), el = this.element; + + this.resizing = true; + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; + + // bugfix for http://dev.jquery.com/ticket/1749 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); + } + + //Opera fixing relative position + if ($.browser.opera && (/relative/).test(el.css('position'))) + el.css({ position: 'relative', top: 'auto', left: 'auto' }); + + this._renderProxy(); + + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); + + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; + } + + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; + + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); + + var cursor = $('.ui-resizable-' + this.axis).css('cursor'); + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); + + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; + }, + + _mouseDrag: function(event) { + + //Increase performance, avoid regex + var el = this.helper, o = this.options, props = {}, + self = this, smp = this.originalMousePosition, a = this.axis; + + var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; + var trigger = this._change[a]; + if (!trigger) return false; + + // Calculate the attrs that will be change + var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; + + // Put this in the mouseDrag handler since the user can start pressing shift while resizing + this._updateVirtualBoundaries(event.shiftKey); + if (this._aspectRatio || event.shiftKey) + data = this._updateRatio(data, event); + + data = this._respectSize(data, event); + + // plugins callbacks need to be called first + this._propagate("resize", event); + + el.css({ + top: this.position.top + "px", left: this.position.left + "px", + width: this.size.width + "px", height: this.size.height + "px" + }); + + if (!this._helper && this._proportionallyResizeElements.length) + this._proportionallyResize(); + + this._updateCache(data); + + // calling the user callback at the end + this._trigger('resize', event, this.ui()); + + return false; + }, + + _mouseStop: function(event) { + + this.resizing = false; + var o = this.options, self = this; + + if(this._helper) { + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + if (!o.animate) + this.element.css($.extend(s, { top: top, left: left })); + + self.helper.height(self.size.height); + self.helper.width(self.size.width); + + if (this._helper && !o.animate) this._proportionallyResize(); + } + + $('body').css('cursor', 'auto'); + + this.element.removeClass("ui-resizable-resizing"); + + this._propagate("stop", event); + + if (this._helper) this.helper.remove(); + return false; + + }, + + _updateVirtualBoundaries: function(forceAspectRatio) { + var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; + + b = { + minWidth: isNumber(o.minWidth) ? o.minWidth : 0, + maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, + minHeight: isNumber(o.minHeight) ? o.minHeight : 0, + maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity + }; + + if(this._aspectRatio || forceAspectRatio) { + // We want to create an enclosing box whose aspect ration is the requested one + // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension + pMinWidth = b.minHeight * this.aspectRatio; + pMinHeight = b.minWidth / this.aspectRatio; + pMaxWidth = b.maxHeight * this.aspectRatio; + pMaxHeight = b.maxWidth / this.aspectRatio; + + if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; + if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; + if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; + if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; + } + this._vBoundaries = b; + }, + + _updateCache: function(data) { + var o = this.options; + this.offset = this.helper.offset(); + if (isNumber(data.left)) this.position.left = data.left; + if (isNumber(data.top)) this.position.top = data.top; + if (isNumber(data.height)) this.size.height = data.height; + if (isNumber(data.width)) this.size.width = data.width; + }, + + _updateRatio: function(data, event) { + + var o = this.options, cpos = this.position, csize = this.size, a = this.axis; + + if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); + else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); + + if (a == 'sw') { + data.left = cpos.left + (csize.width - data.width); + data.top = null; + } + if (a == 'nw') { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); + } + + return data; + }, + + _respectSize: function(data, event) { + + var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); + + if (isminw) data.width = o.minWidth; + if (isminh) data.height = o.minHeight; + if (ismaxw) data.width = o.maxWidth; + if (ismaxh) data.height = o.maxHeight; + + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); + + if (isminw && cw) data.left = dw - o.minWidth; + if (ismaxw && cw) data.left = dw - o.maxWidth; + if (isminh && ch) data.top = dh - o.minHeight; + if (ismaxh && ch) data.top = dh - o.maxHeight; + + // fixing jump error on top/left - bug #2330 + var isNotwh = !data.width && !data.height; + if (isNotwh && !data.left && data.top) data.top = null; + else if (isNotwh && !data.top && data.left) data.left = null; + + return data; + }, + + _proportionallyResize: function() { + + var o = this.options; + if (!this._proportionallyResizeElements.length) return; + var element = this.helper || this.element; + + for (var i=0; i < this._proportionallyResizeElements.length; i++) { + + var prel = this._proportionallyResizeElements[i]; + + if (!this.borderDif) { + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; + + this.borderDif = $.map(b, function(v, i) { + var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; + return border + padding; + }); + } + + if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) + continue; + + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); + + }; + + }, + + _renderProxy: function() { + + var el = this.element, o = this.options; + this.elementOffset = el.offset(); + + if(this._helper) { + + this.helper = this.helper || $('
                        '); + + // fix ie6 offset TODO: This seems broken + var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), + pxyoffset = ( ie6 ? 2 : -1 ); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() + pxyoffset, + height: this.element.outerHeight() + pxyoffset, + position: 'absolute', + left: this.elementOffset.left - ie6offset +'px', + top: this.elementOffset.top - ie6offset +'px', + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; + } + + }, + + _change: { + e: function(event, dx, dy) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + } + }, + + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n != "resize" && this._trigger(n, event, this.ui())); + }, + + plugins: {}, + + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } + +}); + +$.extend($.ui.resizable, { + version: "1.8.16" +}); + +/* + * Resizable Extensions + */ + +$.ui.plugin.add("resizable", "alsoResize", { + + start: function (event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var _store = function (exp) { + $(exp).each(function() { + var el = $(this); + el.data("resizable-alsoresize", { + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), + left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10), + position: el.css('position') // to reset Opera on stop() + }); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } + else { $.each(o.alsoResize, function (exp) { _store(exp); }); } + }else{ + _store(o.alsoResize); + } + }, + + resize: function (event, ui) { + var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; + + var delta = { + height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, + top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 + }, + + _alsoResize = function (exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, + css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; + + $.each(css, function (i, prop) { + var sum = (start[prop]||0) + (delta[prop]||0); + if (sum && sum >= 0) + style[prop] = sum || null; + }); + + // Opera fixing relative position + if ($.browser.opera && /relative/.test(el.css('position'))) { + self._revertToRelativePosition = true; + el.css({ position: 'absolute', top: 'auto', left: 'auto' }); + } + + el.css(style); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); + }else{ + _alsoResize(o.alsoResize); + } + }, + + stop: function (event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var _reset = function (exp) { + $(exp).each(function() { + var el = $(this); + // reset position for Opera - no need to verify it was changed + el.css({ position: el.data("resizable-alsoresize").position }); + }); + }; + + if (self._revertToRelativePosition) { + self._revertToRelativePosition = false; + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function (exp) { _reset(exp); }); + }else{ + _reset(o.alsoResize); + } + } + + $(this).removeData("resizable-alsoresize"); + } +}); + +$.ui.plugin.add("resizable", "animate", { + + stop: function(event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + self.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(self.element.css('width'), 10), + height: parseInt(self.element.css('height'), 10), + top: parseInt(self.element.css('top'), 10), + left: parseInt(self.element.css('left'), 10) + }; + + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); + + // propagating resize, and updating values for each animation step + self._updateCache(data); + self._propagate("resize", event); + + } + } + ); + } + +}); + +$.ui.plugin.add("resizable", "containment", { + + start: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, el = self.element; + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + if (!ce) return; + + self.containerElement = $(ce); + + if (/document/.test(oc) || oc == document) { + self.containerOffset = { left: 0, top: 0 }; + self.containerPosition = { left: 0, top: 0 }; + + self.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; + } + + // i'm a node, so compute top, left, right, bottom + else { + var element = $(ce), p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); + + self.containerOffset = element.offset(); + self.containerPosition = element.position(); + self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; + + var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); + + self.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; + } + }, + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, + ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, + pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; + + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; + + if (cp.left < (self._helper ? co.left : 0)) { + self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); + if (pRatio) self.size.height = self.size.width / o.aspectRatio; + self.position.left = o.helper ? co.left : 0; + } + + if (cp.top < (self._helper ? co.top : 0)) { + self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); + if (pRatio) self.size.width = self.size.height * o.aspectRatio; + self.position.top = self._helper ? co.top : 0; + } + + self.offset.left = self.parentData.left+self.position.left; + self.offset.top = self.parentData.top+self.position.top; + + var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), + hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); + + var isParent = self.containerElement.get(0) == self.element.parent().get(0), + isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); + + if(isParent && isOffsetRelative) woset -= self.parentData.left; + + if (woset + self.size.width >= self.parentData.width) { + self.size.width = self.parentData.width - woset; + if (pRatio) self.size.height = self.size.width / self.aspectRatio; + } + + if (hoset + self.size.height >= self.parentData.height) { + self.size.height = self.parentData.height - hoset; + if (pRatio) self.size.width = self.size.height * self.aspectRatio; + } + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"), o = self.options, cp = self.position, + co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; + + var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; + + if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + if (self._helper && !o.animate && (/static/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + } +}); + +$.ui.plugin.add("resizable", "ghost", { + + start: function(event, ui) { + + var self = $(this).data("resizable"), o = self.options, cs = self.size; + + self.ghost = self.originalElement.clone(); + self.ghost + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass('ui-resizable-ghost') + .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + + self.ghost.appendTo(self.helper); + + }, + + resize: function(event, ui){ + var self = $(this).data("resizable"), o = self.options; + if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"), o = self.options; + if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); + } + +}); + +$.ui.plugin.add("resizable", "grid", { + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; + var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); + + if (/^(se|s|e)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + } + else if (/^(ne)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + } + else if (/^(sw)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.left = op.left - ox; + } + else { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + self.position.left = op.left - ox; + } + } + +}); + +var num = function(v) { + return parseInt(v, 10) || 0; +}; + +var isNumber = function(value) { + return !isNaN(parseInt(value, 10)); +}; + +})(jQuery); +/* + * jQuery UI Selectable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.selectable", $.ui.mouse, { + options: { + appendTo: 'body', + autoRefresh: true, + distance: 0, + filter: '*', + tolerance: 'touch' + }, + _create: function() { + var self = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(self.options.filter, self.element[0]); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("
                        "); + }, + + destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled") + .removeData("selectable") + .unbind(".selectable"); + this._mouseDestroy(); + + return this; + }, + + _mouseStart: function(event) { + var self = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) + return; + + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected'); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + self._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + return false; + } + }); + + }, + + _mouseDrag: function(event) { + var self = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == self.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + self._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if (event.metaKey && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var self = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + self._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + self._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +}); + +$.extend($.ui.selectable, { + version: "1.8.16" +}); + +})(jQuery); +/* + * jQuery UI Sortable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.sortable", $.ui.mouse, { + widgetEventPrefix: "sort", + options: { + appendTo: "parent", + axis: false, + connectWith: false, + containment: false, + cursor: 'auto', + cursorAt: false, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: '> *', + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000 + }, + _create: function() { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are being displayed horizontally + this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + }, + + destroy: function() { + this.element + .removeClass("ui-sortable ui-sortable-disabled") + .removeData("sortable") + .unbind(".sortable"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) + this.items[i].item.removeData("sortable-item"); + + return this; + }, + + _setOption: function(key, value){ + if ( key === "disabled" ) { + this.options[ key ] = value; + + this.widget() + [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" ); + } else { + // Don't call widget base _setOption for disable as it adds ui-state-disabled class + $.Widget.prototype._setOption.apply(this, arguments); + } + }, + + _mouseCapture: function(event, overrideHandle) { + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { + if($.data(this, 'sortable-item') == self) { + currentItem = $(this); + return false; + } + }); + if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target); + + if(!currentItem) return false; + if(this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); + if(!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart: function(event, overrideHandle, noActivation) { + + var o = this.options, self = this; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + if(o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); + } + + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } + + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if(!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } + } + + //Prepare possible droppables + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag: function(event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if(this.options.scroll) { + var o = this.options, scrolled = false; + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + if(itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) + //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event, noPropagation) { + + if(!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if(this.options.revert) { + var self = this; + var cur = self.placeholder.offset(); + + self.reverting = true; + + $(this.helper).animate({ + left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function() { + self._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel: function() { + + var self = this; + + if(this.dragging) { + + this._mouseUp({ target: null }); + + if(this.options.helper == "original") + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + else + this.currentItem.show(); + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + this.containers[i]._trigger("deactivate", null, self._uiHash(this)); + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, self._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + } + + return this; + + }, + + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); + }); + + if(!str.length && o.key) { + str.push(o.key + '='); + } + + return str.join('&'); + + }, + + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if( this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function(item) { + + var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + + }, + + _intersectsWithSides: function(item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); + }, + + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + return this; + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; + }, + + _getItemsAsjQuery: function(connected) { + + var self = this; + var items = []; + var queries = []; + var connectWith = this._connectWith(); + + if(connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], 'sortable'); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); + } + }; + }; + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); + + for (var i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + }; + + return $(items); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find(":data(sortable-item)"); + + for (var i=0; i < this.items.length; i++) { + + for (var j=0; j < list.length; j++) { + if(list[j] == this.items[i].item[0]) + this.items.splice(i,1); + }; + + }; + + }, + + _refreshItems: function(event) { + + this.items = []; + this.containers = [this]; + var items = this.items; + var self = this; + var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; + var connectWith = this._connectWith(); + + if(connectWith) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], 'sortable'); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + }; + }; + } + + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; + + for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); + + item.data('sortable-item', targetData); // Data for target checking (mouse manager) + + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + }; + }; + + }, + + refreshPositions: function(fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + for (var i = this.items.length - 1; i >= 0; i--){ + var item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + var p = t.offset(); + item.left = p.left; + item.top = p.top; + }; + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--){ + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + }; + } + + return this; + }, + + _createPlaceholder: function(that) { + + var self = that || this, o = self.options; + + if(!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element: function() { + + var el = $(document.createElement(self.currentItem[0].nodeName)) + .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if(!className) + el.style.visibility = "hidden"; + + return el; + }, + update: function(container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; + if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; + } + }; + } + + //Create the placeholder + self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); + + //Append it after the actual current item + self.currentItem.after(self.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(self, self.placeholder); + + }, + + _contactContainers: function(event) { + + // get innermost container that intersects with item + var innermostContainer = null, innermostIndex = null; + + + for (var i = this.containers.length - 1; i >= 0; i--){ + + // never consider a container that's located within the item itself + if($.ui.contains(this.currentItem[0], this.containers[i].element[0])) + continue; + + if(this._intersectsWith(this.containers[i].containerCache)) { + + // if we've already found a container and it's more "inner" than this, then continue + if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) + continue; + + innermostContainer = this.containers[i]; + innermostIndex = i; + + } else { + // container doesn't intersect. trigger "out" event if necessary + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + // if no intersecting containers found, return + if(!innermostContainer) return; + + // move the item into the container if it's not there already + if(this.containers.length === 1) { + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } else if(this.currentContainer != this.containers[innermostIndex]) { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; + for (var j = this.items.length - 1; j >= 0; j--) { + if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; + var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + } + } + + if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + return; + + this.currentContainer = this.containers[innermostIndex]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } + + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); + + if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + + if(helper[0] == this.currentItem[0]) + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + + if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.currentItem.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange: function(event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var self = this, counter = this.counter; + + window.setTimeout(function() { + if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + },0); + + }, + + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = [], self = this; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if(this.helper[0] == this.currentItem[0]) { + for(var i in this._storedCSS) { + if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed + if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element + if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + for (var i = this.containers.length - 1; i >= 0; i--){ + if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + } + }; + }; + + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity + if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + return false; + } + + if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + + if(!noPropagation) { + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger: function() { + if ($.Widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash: function(inst) { + var self = inst || this; + return { + helper: self.helper, + placeholder: self.placeholder || $([]), + position: self.position, + originalPosition: self.originalPosition, + offset: self.positionAbs, + item: self.currentItem, + sender: inst ? inst.element : null + }; + } + +}); + +$.extend($.ui.sortable, { + version: "1.8.16" +}); + +})(jQuery); +/* + * jQuery UI Accordion 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget( "ui.accordion", { + options: { + active: 0, + animated: "slide", + autoHeight: true, + clearStyle: false, + collapsible: false, + event: "click", + fillSpace: false, + header: "> li > :first-child,> :not(li):even", + icons: { + header: "ui-icon-triangle-1-e", + headerSelected: "ui-icon-triangle-1-s" + }, + navigation: false, + navigationFilter: function() { + return this.href.toLowerCase() === location.href.toLowerCase(); + } + }, + + _create: function() { + var self = this, + options = self.options; + + self.running = 0; + + self.element + .addClass( "ui-accordion ui-widget ui-helper-reset" ) + // in lack of child-selectors in CSS + // we need to mark top-LIs in a UL-accordion for some IE-fix + .children( "li" ) + .addClass( "ui-accordion-li-fix" ); + + self.headers = self.element.find( options.header ) + .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ) + .bind( "mouseenter.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-hover" ); + }) + .bind( "mouseleave.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( "ui-state-hover" ); + }) + .bind( "focus.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-focus" ); + }) + .bind( "blur.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( "ui-state-focus" ); + }); + + self.headers.next() + .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); + + if ( options.navigation ) { + var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 ); + if ( current.length ) { + var header = current.closest( ".ui-accordion-header" ); + if ( header.length ) { + // anchor within header + self.active = header; + } else { + // anchor within content + self.active = current.closest( ".ui-accordion-content" ).prev(); + } + } + } + + self.active = self._findActive( self.active || options.active ) + .addClass( "ui-state-default ui-state-active" ) + .toggleClass( "ui-corner-all" ) + .toggleClass( "ui-corner-top" ); + self.active.next().addClass( "ui-accordion-content-active" ); + + self._createIcons(); + self.resize(); + + // ARIA + self.element.attr( "role", "tablist" ); + + self.headers + .attr( "role", "tab" ) + .bind( "keydown.accordion", function( event ) { + return self._keydown( event ); + }) + .next() + .attr( "role", "tabpanel" ); + + self.headers + .not( self.active || "" ) + .attr({ + "aria-expanded": "false", + "aria-selected": "false", + tabIndex: -1 + }) + .next() + .hide(); + + // make sure at least one header is in the tab order + if ( !self.active.length ) { + self.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + self.active + .attr({ + "aria-expanded": "true", + "aria-selected": "true", + tabIndex: 0 + }); + } + + // only need links in tab order for Safari + if ( !$.browser.safari ) { + self.headers.find( "a" ).attr( "tabIndex", -1 ); + } + + if ( options.event ) { + self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) { + self._clickHandler.call( self, event, this ); + event.preventDefault(); + }); + } + }, + + _createIcons: function() { + var options = this.options; + if ( options.icons ) { + $( "" ) + .addClass( "ui-icon " + options.icons.header ) + .prependTo( this.headers ); + this.active.children( ".ui-icon" ) + .toggleClass(options.icons.header) + .toggleClass(options.icons.headerSelected); + this.element.addClass( "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this.headers.children( ".ui-icon" ).remove(); + this.element.removeClass( "ui-accordion-icons" ); + }, + + destroy: function() { + var options = this.options; + + this.element + .removeClass( "ui-accordion ui-widget ui-helper-reset" ) + .removeAttr( "role" ); + + this.headers + .unbind( ".accordion" ) + .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeAttr( "role" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-selected" ) + .removeAttr( "tabIndex" ); + + this.headers.find( "a" ).removeAttr( "tabIndex" ); + this._destroyIcons(); + var contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role" ) + .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); + if ( options.autoHeight || options.fillHeight ) { + contents.css( "height", "" ); + } + + return $.Widget.prototype.destroy.call( this ); + }, + + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + + if ( key == "active" ) { + this.activate( value ); + } + if ( key == "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + // #5332 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + if ( key == "disabled" ) { + this.headers.add(this.headers.next()) + [ value ? "addClass" : "removeClass" ]( + "ui-accordion-disabled ui-state-disabled" ); + } + }, + + _keydown: function( event ) { + if ( this.options.disabled || event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._clickHandler( { target: event.target }, event.target ); + event.preventDefault(); + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + toFocus.focus(); + return false; + } + + return true; + }, + + resize: function() { + var options = this.options, + maxHeight; + + if ( options.fillSpace ) { + if ( $.browser.msie ) { + var defOverflow = this.element.parent().css( "overflow" ); + this.element.parent().css( "overflow", "hidden"); + } + maxHeight = this.element.parent().height(); + if ($.browser.msie) { + this.element.parent().css( "overflow", defOverflow ); + } + + this.headers.each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.headers.next() + .each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( options.autoHeight ) { + maxHeight = 0; + this.headers.next() + .each(function() { + maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); + }) + .height( maxHeight ); + } + + return this; + }, + + activate: function( index ) { + // TODO this gets called on init, changing the option without an explicit call for that + this.options.active = index; + // call clickHandler with custom event + var active = this._findActive( index )[ 0 ]; + this._clickHandler( { target: active }, active ); + + return this; + }, + + _findActive: function( selector ) { + return selector + ? typeof selector === "number" + ? this.headers.filter( ":eq(" + selector + ")" ) + : this.headers.not( this.headers.not( selector ) ) + : selector === false + ? $( [] ) + : this.headers.filter( ":eq(0)" ); + }, + + // TODO isn't event.target enough? why the separate target argument? + _clickHandler: function( event, target ) { + var options = this.options; + if ( options.disabled ) { + return; + } + + // called only when using activate(false) to close all parts programmatically + if ( !event.target ) { + if ( !options.collapsible ) { + return; + } + this.active + .removeClass( "ui-state-active ui-corner-top" ) + .addClass( "ui-state-default ui-corner-all" ) + .children( ".ui-icon" ) + .removeClass( options.icons.headerSelected ) + .addClass( options.icons.header ); + this.active.next().addClass( "ui-accordion-content-active" ); + var toHide = this.active.next(), + data = { + options: options, + newHeader: $( [] ), + oldHeader: options.active, + newContent: $( [] ), + oldContent: toHide + }, + toShow = ( this.active = $( [] ) ); + this._toggle( toShow, toHide, data ); + return; + } + + // get the click target + var clicked = $( event.currentTarget || target ), + clickedIsActive = clicked[0] === this.active[0]; + + // TODO the option is changed, is that correct? + // TODO if it is correct, shouldn't that happen after determining that the click is valid? + options.active = options.collapsible && clickedIsActive ? + false : + this.headers.index( clicked ); + + // if animations are still active, or the active header is the target, ignore click + if ( this.running || ( !options.collapsible && clickedIsActive ) ) { + return; + } + + // find elements to show and hide + var active = this.active, + toShow = clicked.next(), + toHide = this.active.next(), + data = { + options: options, + newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, + oldHeader: this.active, + newContent: clickedIsActive && options.collapsible ? $([]) : toShow, + oldContent: toHide + }, + down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); + + // when the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $([]) : clicked; + this._toggle( toShow, toHide, data, clickedIsActive, down ); + + // switch classes + active + .removeClass( "ui-state-active ui-corner-top" ) + .addClass( "ui-state-default ui-corner-all" ) + .children( ".ui-icon" ) + .removeClass( options.icons.headerSelected ) + .addClass( options.icons.header ); + if ( !clickedIsActive ) { + clicked + .removeClass( "ui-state-default ui-corner-all" ) + .addClass( "ui-state-active ui-corner-top" ) + .children( ".ui-icon" ) + .removeClass( options.icons.header ) + .addClass( options.icons.headerSelected ); + clicked + .next() + .addClass( "ui-accordion-content-active" ); + } + + return; + }, + + _toggle: function( toShow, toHide, data, clickedIsActive, down ) { + var self = this, + options = self.options; + + self.toShow = toShow; + self.toHide = toHide; + self.data = data; + + var complete = function() { + if ( !self ) { + return; + } + return self._completed.apply( self, arguments ); + }; + + // trigger changestart event + self._trigger( "changestart", null, self.data ); + + // count elements to animate + self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); + + if ( options.animated ) { + var animOptions = {}; + + if ( options.collapsible && clickedIsActive ) { + animOptions = { + toShow: $( [] ), + toHide: toHide, + complete: complete, + down: down, + autoHeight: options.autoHeight || options.fillSpace + }; + } else { + animOptions = { + toShow: toShow, + toHide: toHide, + complete: complete, + down: down, + autoHeight: options.autoHeight || options.fillSpace + }; + } + + if ( !options.proxied ) { + options.proxied = options.animated; + } + + if ( !options.proxiedDuration ) { + options.proxiedDuration = options.duration; + } + + options.animated = $.isFunction( options.proxied ) ? + options.proxied( animOptions ) : + options.proxied; + + options.duration = $.isFunction( options.proxiedDuration ) ? + options.proxiedDuration( animOptions ) : + options.proxiedDuration; + + var animations = $.ui.accordion.animations, + duration = options.duration, + easing = options.animated; + + if ( easing && !animations[ easing ] && !$.easing[ easing ] ) { + easing = "slide"; + } + if ( !animations[ easing ] ) { + animations[ easing ] = function( options ) { + this.slide( options, { + easing: easing, + duration: duration || 700 + }); + }; + } + + animations[ easing ]( animOptions ); + } else { + if ( options.collapsible && clickedIsActive ) { + toShow.toggle(); + } else { + toHide.hide(); + toShow.show(); + } + + complete( true ); + } + + // TODO assert that the blur and focus triggers are really necessary, remove otherwise + toHide.prev() + .attr({ + "aria-expanded": "false", + "aria-selected": "false", + tabIndex: -1 + }) + .blur(); + toShow.prev() + .attr({ + "aria-expanded": "true", + "aria-selected": "true", + tabIndex: 0 + }) + .focus(); + }, + + _completed: function( cancel ) { + this.running = cancel ? 0 : --this.running; + if ( this.running ) { + return; + } + + if ( this.options.clearStyle ) { + this.toShow.add( this.toHide ).css({ + height: "", + overflow: "" + }); + } + + // other classes are removed before the animation; this one needs to stay until completed + this.toHide.removeClass( "ui-accordion-content-active" ); + // Work around for rendering bug in IE (#5421) + if ( this.toHide.length ) { + this.toHide.parent()[0].className = this.toHide.parent()[0].className; + } + + this._trigger( "change", null, this.data ); + } +}); + +$.extend( $.ui.accordion, { + version: "1.8.16", + animations: { + slide: function( options, additions ) { + options = $.extend({ + easing: "swing", + duration: 300 + }, options, additions ); + if ( !options.toHide.size() ) { + options.toShow.animate({ + height: "show", + paddingTop: "show", + paddingBottom: "show" + }, options ); + return; + } + if ( !options.toShow.size() ) { + options.toHide.animate({ + height: "hide", + paddingTop: "hide", + paddingBottom: "hide" + }, options ); + return; + } + var overflow = options.toShow.css( "overflow" ), + percentDone = 0, + showProps = {}, + hideProps = {}, + fxAttrs = [ "height", "paddingTop", "paddingBottom" ], + originalWidth; + // fix width before calculating height of hidden element + var s = options.toShow; + originalWidth = s[0].style.width; + s.width( parseInt( s.parent().width(), 10 ) + - parseInt( s.css( "paddingLeft" ), 10 ) + - parseInt( s.css( "paddingRight" ), 10 ) + - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 ) + - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) ); + + $.each( fxAttrs, function( i, prop ) { + hideProps[ prop ] = "hide"; + + var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ); + showProps[ prop ] = { + value: parts[ 1 ], + unit: parts[ 2 ] || "px" + }; + }); + options.toShow.css({ height: 0, overflow: "hidden" }).show(); + options.toHide + .filter( ":hidden" ) + .each( options.complete ) + .end() + .filter( ":visible" ) + .animate( hideProps, { + step: function( now, settings ) { + // only calculate the percent when animating height + // IE gets very inconsistent results when animating elements + // with small values, which is common for padding + if ( settings.prop == "height" ) { + percentDone = ( settings.end - settings.start === 0 ) ? 0 : + ( settings.now - settings.start ) / ( settings.end - settings.start ); + } + + options.toShow[ 0 ].style[ settings.prop ] = + ( percentDone * showProps[ settings.prop ].value ) + + showProps[ settings.prop ].unit; + }, + duration: options.duration, + easing: options.easing, + complete: function() { + if ( !options.autoHeight ) { + options.toShow.css( "height", "" ); + } + options.toShow.css({ + width: originalWidth, + overflow: overflow + }); + options.complete(); + } + }); + }, + bounceslide: function( options ) { + this.slide( options, { + easing: options.down ? "easeOutBounce" : "swing", + duration: options.down ? 1000 : 200 + }); + } + } +}); + +})( jQuery ); +/* + * jQuery UI Autocomplete 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function( $, undefined ) { + +// used to prevent race conditions with remote data sources +var requestIndex = 0; + +$.widget( "ui.autocomplete", { + options: { + appendTo: "body", + autoFocus: false, + delay: 300, + minLength: 1, + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null + }, + + pending: 0, + + _create: function() { + var self = this, + doc = this.element[ 0 ].ownerDocument, + suppressKeyPress; + + this.element + .addClass( "ui-autocomplete-input" ) + .attr( "autocomplete", "off" ) + // TODO verify these actually work as intended + .attr({ + role: "textbox", + "aria-autocomplete": "list", + "aria-haspopup": "true" + }) + .bind( "keydown.autocomplete", function( event ) { + if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) { + return; + } + + suppressKeyPress = false; + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + self._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + self._move( "nextPage", event ); + break; + case keyCode.UP: + self._move( "previous", event ); + // prevent moving cursor to beginning of text field in some browsers + event.preventDefault(); + break; + case keyCode.DOWN: + self._move( "next", event ); + // prevent moving cursor to end of text field in some browsers + event.preventDefault(); + break; + case keyCode.ENTER: + case keyCode.NUMPAD_ENTER: + // when menu is open and has focus + if ( self.menu.active ) { + // #6055 - Opera still allows the keypress to occur + // which causes forms to submit + suppressKeyPress = true; + event.preventDefault(); + } + //passthrough - ENTER and TAB both select the current element + case keyCode.TAB: + if ( !self.menu.active ) { + return; + } + self.menu.select( event ); + break; + case keyCode.ESCAPE: + self.element.val( self.term ); + self.close( event ); + break; + default: + // keypress is triggered before the input value is changed + clearTimeout( self.searching ); + self.searching = setTimeout(function() { + // only search if the value has changed + if ( self.term != self.element.val() ) { + self.selectedItem = null; + self.search( null, event ); + } + }, self.options.delay ); + break; + } + }) + .bind( "keypress.autocomplete", function( event ) { + if ( suppressKeyPress ) { + suppressKeyPress = false; + event.preventDefault(); + } + }) + .bind( "focus.autocomplete", function() { + if ( self.options.disabled ) { + return; + } + + self.selectedItem = null; + self.previous = self.element.val(); + }) + .bind( "blur.autocomplete", function( event ) { + if ( self.options.disabled ) { + return; + } + + clearTimeout( self.searching ); + // clicks on the menu (or a button to trigger a search) will cause a blur event + self.closing = setTimeout(function() { + self.close( event ); + self._change( event ); + }, 150 ); + }); + this._initSource(); + this.response = function() { + return self._response.apply( self, arguments ); + }; + this.menu = $( "
                          " ) + .addClass( "ui-autocomplete" ) + .appendTo( $( this.options.appendTo || "body", doc )[0] ) + // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) + .mousedown(function( event ) { + // clicking on the scrollbar causes focus to shift to the body + // but we can't detect a mouseup or a click immediately afterward + // so we have to track the next mousedown and close the menu if + // the user clicks somewhere outside of the autocomplete + var menuElement = self.menu.element[ 0 ]; + if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { + setTimeout(function() { + $( document ).one( 'mousedown', function( event ) { + if ( event.target !== self.element[ 0 ] && + event.target !== menuElement && + !$.ui.contains( menuElement, event.target ) ) { + self.close(); + } + }); + }, 1 ); + } + + // use another timeout to make sure the blur-event-handler on the input was already triggered + setTimeout(function() { + clearTimeout( self.closing ); + }, 13); + }) + .menu({ + focus: function( event, ui ) { + var item = ui.item.data( "item.autocomplete" ); + if ( false !== self._trigger( "focus", event, { item: item } ) ) { + // use value to match what will end up in the input, if it was a key event + if ( /^key/.test(event.originalEvent.type) ) { + self.element.val( item.value ); + } + } + }, + selected: function( event, ui ) { + var item = ui.item.data( "item.autocomplete" ), + previous = self.previous; + + // only trigger when focus was lost (click on menu) + if ( self.element[0] !== doc.activeElement ) { + self.element.focus(); + self.previous = previous; + // #6109 - IE triggers two focus events and the second + // is asynchronous, so we need to reset the previous + // term synchronously and asynchronously :-( + setTimeout(function() { + self.previous = previous; + self.selectedItem = item; + }, 1); + } + + if ( false !== self._trigger( "select", event, { item: item } ) ) { + self.element.val( item.value ); + } + // reset the term after the select event + // this allows custom select handling to work properly + self.term = self.element.val(); + + self.close( event ); + self.selectedItem = item; + }, + blur: function( event, ui ) { + // don't set the value of the text field if it's already correct + // this prevents moving the cursor unnecessarily + if ( self.menu.element.is(":visible") && + ( self.element.val() !== self.term ) ) { + self.element.val( self.term ); + } + } + }) + .zIndex( this.element.zIndex() + 1 ) + // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 + .css({ top: 0, left: 0 }) + .hide() + .data( "menu" ); + if ( $.fn.bgiframe ) { + this.menu.element.bgiframe(); + } + }, + + destroy: function() { + this.element + .removeClass( "ui-autocomplete-input" ) + .removeAttr( "autocomplete" ) + .removeAttr( "role" ) + .removeAttr( "aria-autocomplete" ) + .removeAttr( "aria-haspopup" ); + this.menu.element.remove(); + $.Widget.prototype.destroy.call( this ); + }, + + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + if ( key === "source" ) { + this._initSource(); + } + if ( key === "appendTo" ) { + this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) + } + if ( key === "disabled" && value && this.xhr ) { + this.xhr.abort(); + } + }, + + _initSource: function() { + var self = this, + array, + url; + if ( $.isArray(this.options.source) ) { + array = this.options.source; + this.source = function( request, response ) { + response( $.ui.autocomplete.filter(array, request.term) ); + }; + } else if ( typeof this.options.source === "string" ) { + url = this.options.source; + this.source = function( request, response ) { + if ( self.xhr ) { + self.xhr.abort(); + } + self.xhr = $.ajax({ + url: url, + data: request, + dataType: "json", + autocompleteRequest: ++requestIndex, + success: function( data, status ) { + if ( this.autocompleteRequest === requestIndex ) { + response( data ); + } + }, + error: function() { + if ( this.autocompleteRequest === requestIndex ) { + response( [] ); + } + } + }); + }; + } else { + this.source = this.options.source; + } + }, + + search: function( value, event ) { + value = value != null ? value : this.element.val(); + + // always save the actual value, not the one passed as an argument + this.term = this.element.val(); + + if ( value.length < this.options.minLength ) { + return this.close( event ); + } + + clearTimeout( this.closing ); + if ( this._trigger( "search", event ) === false ) { + return; + } + + return this._search( value ); + }, + + _search: function( value ) { + this.pending++; + this.element.addClass( "ui-autocomplete-loading" ); + + this.source( { term: value }, this.response ); + }, + + _response: function( content ) { + if ( !this.options.disabled && content && content.length ) { + content = this._normalize( content ); + this._suggest( content ); + this._trigger( "open" ); + } else { + this.close(); + } + this.pending--; + if ( !this.pending ) { + this.element.removeClass( "ui-autocomplete-loading" ); + } + }, + + close: function( event ) { + clearTimeout( this.closing ); + if ( this.menu.element.is(":visible") ) { + this.menu.element.hide(); + this.menu.deactivate(); + this._trigger( "close", event ); + } + }, + + _change: function( event ) { + if ( this.previous !== this.element.val() ) { + this._trigger( "change", event, { item: this.selectedItem } ); + } + }, + + _normalize: function( items ) { + // assume all items have the right format when the first item is complete + if ( items.length && items[0].label && items[0].value ) { + return items; + } + return $.map( items, function(item) { + if ( typeof item === "string" ) { + return { + label: item, + value: item + }; + } + return $.extend({ + label: item.label || item.value, + value: item.value || item.label + }, item ); + }); + }, + + _suggest: function( items ) { + var ul = this.menu.element + .empty() + .zIndex( this.element.zIndex() + 1 ); + this._renderMenu( ul, items ); + // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate + this.menu.deactivate(); + this.menu.refresh(); + + // size and position menu + ul.show(); + this._resizeMenu(); + ul.position( $.extend({ + of: this.element + }, this.options.position )); + + if ( this.options.autoFocus ) { + this.menu.next( new $.Event("mouseover") ); + } + }, + + _resizeMenu: function() { + var ul = this.menu.element; + ul.outerWidth( Math.max( + ul.width( "" ).outerWidth(), + this.element.outerWidth() + ) ); + }, + + _renderMenu: function( ul, items ) { + var self = this; + $.each( items, function( index, item ) { + self._renderItem( ul, item ); + }); + }, + + _renderItem: function( ul, item) { + return $( "
                        • " ) + .data( "item.autocomplete", item ) + .append( $( "" ).text( item.label ) ) + .appendTo( ul ); + }, + + _move: function( direction, event ) { + if ( !this.menu.element.is(":visible") ) { + this.search( null, event ); + return; + } + if ( this.menu.first() && /^previous/.test(direction) || + this.menu.last() && /^next/.test(direction) ) { + this.element.val( this.term ); + this.menu.deactivate(); + return; + } + this.menu[ direction ]( event ); + }, + + widget: function() { + return this.menu.element; + } +}); + +$.extend( $.ui.autocomplete, { + escapeRegex: function( value ) { + return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + }, + filter: function(array, term) { + var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); + return $.grep( array, function(value) { + return matcher.test( value.label || value.value || value ); + }); + } +}); + +}( jQuery )); + +/* + * jQuery UI Menu (not officially released) + * + * This widget isn't yet finished and the API is subject to change. We plan to finish + * it for the next release. You're welcome to give it a try anyway and give us feedback, + * as long as you're okay with migrating your code later on. We can help with that, too. + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function($) { + +$.widget("ui.menu", { + _create: function() { + var self = this; + this.element + .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") + .attr({ + role: "listbox", + "aria-activedescendant": "ui-active-menuitem" + }) + .click(function( event ) { + if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { + return; + } + // temporary + event.preventDefault(); + self.select( event ); + }); + this.refresh(); + }, + + refresh: function() { + var self = this; + + // don't refresh list items that are already adapted + var items = this.element.children("li:not(.ui-menu-item):has(a)") + .addClass("ui-menu-item") + .attr("role", "menuitem"); + + items.children("a") + .addClass("ui-corner-all") + .attr("tabindex", -1) + // mouseenter doesn't work with event delegation + .mouseenter(function( event ) { + self.activate( event, $(this).parent() ); + }) + .mouseleave(function() { + self.deactivate(); + }); + }, + + activate: function( event, item ) { + this.deactivate(); + if (this.hasScroll()) { + var offset = item.offset().top - this.element.offset().top, + scroll = this.element.scrollTop(), + elementHeight = this.element.height(); + if (offset < 0) { + this.element.scrollTop( scroll + offset); + } else if (offset >= elementHeight) { + this.element.scrollTop( scroll + offset - elementHeight + item.height()); + } + } + this.active = item.eq(0) + .children("a") + .addClass("ui-state-hover") + .attr("id", "ui-active-menuitem") + .end(); + this._trigger("focus", event, { item: item }); + }, + + deactivate: function() { + if (!this.active) { return; } + + this.active.children("a") + .removeClass("ui-state-hover") + .removeAttr("id"); + this._trigger("blur"); + this.active = null; + }, + + next: function(event) { + this.move("next", ".ui-menu-item:first", event); + }, + + previous: function(event) { + this.move("prev", ".ui-menu-item:last", event); + }, + + first: function() { + return this.active && !this.active.prevAll(".ui-menu-item").length; + }, + + last: function() { + return this.active && !this.active.nextAll(".ui-menu-item").length; + }, + + move: function(direction, edge, event) { + if (!this.active) { + this.activate(event, this.element.children(edge)); + return; + } + var next = this.active[direction + "All"](".ui-menu-item").eq(0); + if (next.length) { + this.activate(event, next); + } else { + this.activate(event, this.element.children(edge)); + } + }, + + // TODO merge with previousPage + nextPage: function(event) { + if (this.hasScroll()) { + // TODO merge with no-scroll-else + if (!this.active || this.last()) { + this.activate(event, this.element.children(".ui-menu-item:first")); + return; + } + var base = this.active.offset().top, + height = this.element.height(), + result = this.element.children(".ui-menu-item").filter(function() { + var close = $(this).offset().top - base - height + $(this).height(); + // TODO improve approximation + return close < 10 && close > -10; + }); + + // TODO try to catch this earlier when scrollTop indicates the last page anyway + if (!result.length) { + result = this.element.children(".ui-menu-item:last"); + } + this.activate(event, result); + } else { + this.activate(event, this.element.children(".ui-menu-item") + .filter(!this.active || this.last() ? ":first" : ":last")); + } + }, + + // TODO merge with nextPage + previousPage: function(event) { + if (this.hasScroll()) { + // TODO merge with no-scroll-else + if (!this.active || this.first()) { + this.activate(event, this.element.children(".ui-menu-item:last")); + return; + } + + var base = this.active.offset().top, + height = this.element.height(); + result = this.element.children(".ui-menu-item").filter(function() { + var close = $(this).offset().top - base + height - $(this).height(); + // TODO improve approximation + return close < 10 && close > -10; + }); + + // TODO try to catch this earlier when scrollTop indicates the last page anyway + if (!result.length) { + result = this.element.children(".ui-menu-item:first"); + } + this.activate(event, result); + } else { + this.activate(event, this.element.children(".ui-menu-item") + .filter(!this.active || this.first() ? ":last" : ":first")); + } + }, + + hasScroll: function() { + return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); + }, + + select: function( event ) { + this._trigger("selected", event, { item: this.active }); + } +}); + +}(jQuery)); +/* + * jQuery UI Button 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var lastActive, startXPos, startYPos, clickDragged, + baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", + stateClasses = "ui-state-hover ui-state-active ", + typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", + formResetHandler = function() { + var buttons = $( this ).find( ":ui-button" ); + setTimeout(function() { + buttons.button( "refresh" ); + }, 1 ); + }, + radioGroup = function( radio ) { + var name = radio.name, + form = radio.form, + radios = $( [] ); + if ( name ) { + if ( form ) { + radios = $( form ).find( "[name='" + name + "']" ); + } else { + radios = $( "[name='" + name + "']", radio.ownerDocument ) + .filter(function() { + return !this.form; + }); + } + } + return radios; + }; + +$.widget( "ui.button", { + options: { + disabled: null, + text: true, + label: null, + icons: { + primary: null, + secondary: null + } + }, + _create: function() { + this.element.closest( "form" ) + .unbind( "reset.button" ) + .bind( "reset.button", formResetHandler ); + + if ( typeof this.options.disabled !== "boolean" ) { + this.options.disabled = this.element.propAttr( "disabled" ); + } + + this._determineButtonType(); + this.hasTitle = !!this.buttonElement.attr( "title" ); + + var self = this, + options = this.options, + toggleButton = this.type === "checkbox" || this.type === "radio", + hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ), + focusClass = "ui-state-focus"; + + if ( options.label === null ) { + options.label = this.buttonElement.html(); + } + + if ( this.element.is( ":disabled" ) ) { + options.disabled = true; + } + + this.buttonElement + .addClass( baseClasses ) + .attr( "role", "button" ) + .bind( "mouseenter.button", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-hover" ); + if ( this === lastActive ) { + $( this ).addClass( "ui-state-active" ); + } + }) + .bind( "mouseleave.button", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( hoverClass ); + }) + .bind( "click.button", function( event ) { + if ( options.disabled ) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }); + + this.element + .bind( "focus.button", function() { + // no need to check disabled, focus won't be triggered anyway + self.buttonElement.addClass( focusClass ); + }) + .bind( "blur.button", function() { + self.buttonElement.removeClass( focusClass ); + }); + + if ( toggleButton ) { + this.element.bind( "change.button", function() { + if ( clickDragged ) { + return; + } + self.refresh(); + }); + // if mouse moves between mousedown and mouseup (drag) set clickDragged flag + // prevents issue where button state changes but checkbox/radio checked state + // does not in Firefox (see ticket #6970) + this.buttonElement + .bind( "mousedown.button", function( event ) { + if ( options.disabled ) { + return; + } + clickDragged = false; + startXPos = event.pageX; + startYPos = event.pageY; + }) + .bind( "mouseup.button", function( event ) { + if ( options.disabled ) { + return; + } + if ( startXPos !== event.pageX || startYPos !== event.pageY ) { + clickDragged = true; + } + }); + } + + if ( this.type === "checkbox" ) { + this.buttonElement.bind( "click.button", function() { + if ( options.disabled || clickDragged ) { + return false; + } + $( this ).toggleClass( "ui-state-active" ); + self.buttonElement.attr( "aria-pressed", self.element[0].checked ); + }); + } else if ( this.type === "radio" ) { + this.buttonElement.bind( "click.button", function() { + if ( options.disabled || clickDragged ) { + return false; + } + $( this ).addClass( "ui-state-active" ); + self.buttonElement.attr( "aria-pressed", "true" ); + + var radio = self.element[ 0 ]; + radioGroup( radio ) + .not( radio ) + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + }); + } else { + this.buttonElement + .bind( "mousedown.button", function() { + if ( options.disabled ) { + return false; + } + $( this ).addClass( "ui-state-active" ); + lastActive = this; + $( document ).one( "mouseup", function() { + lastActive = null; + }); + }) + .bind( "mouseup.button", function() { + if ( options.disabled ) { + return false; + } + $( this ).removeClass( "ui-state-active" ); + }) + .bind( "keydown.button", function(event) { + if ( options.disabled ) { + return false; + } + if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) { + $( this ).addClass( "ui-state-active" ); + } + }) + .bind( "keyup.button", function() { + $( this ).removeClass( "ui-state-active" ); + }); + + if ( this.buttonElement.is("a") ) { + this.buttonElement.keyup(function(event) { + if ( event.keyCode === $.ui.keyCode.SPACE ) { + // TODO pass through original event correctly (just as 2nd argument doesn't work) + $( this ).click(); + } + }); + } + } + + // TODO: pull out $.Widget's handling for the disabled option into + // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can + // be overridden by individual plugins + this._setOption( "disabled", options.disabled ); + this._resetButton(); + }, + + _determineButtonType: function() { + + if ( this.element.is(":checkbox") ) { + this.type = "checkbox"; + } else if ( this.element.is(":radio") ) { + this.type = "radio"; + } else if ( this.element.is("input") ) { + this.type = "input"; + } else { + this.type = "button"; + } + + if ( this.type === "checkbox" || this.type === "radio" ) { + // we don't search against the document in case the element + // is disconnected from the DOM + var ancestor = this.element.parents().filter(":last"), + labelSelector = "label[for='" + this.element.attr("id") + "']"; + this.buttonElement = ancestor.find( labelSelector ); + if ( !this.buttonElement.length ) { + ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); + this.buttonElement = ancestor.filter( labelSelector ); + if ( !this.buttonElement.length ) { + this.buttonElement = ancestor.find( labelSelector ); + } + } + this.element.addClass( "ui-helper-hidden-accessible" ); + + var checked = this.element.is( ":checked" ); + if ( checked ) { + this.buttonElement.addClass( "ui-state-active" ); + } + this.buttonElement.attr( "aria-pressed", checked ); + } else { + this.buttonElement = this.element; + } + }, + + widget: function() { + return this.buttonElement; + }, + + destroy: function() { + this.element + .removeClass( "ui-helper-hidden-accessible" ); + this.buttonElement + .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) + .removeAttr( "role" ) + .removeAttr( "aria-pressed" ) + .html( this.buttonElement.find(".ui-button-text").html() ); + + if ( !this.hasTitle ) { + this.buttonElement.removeAttr( "title" ); + } + + $.Widget.prototype.destroy.call( this ); + }, + + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + if ( key === "disabled" ) { + if ( value ) { + this.element.propAttr( "disabled", true ); + } else { + this.element.propAttr( "disabled", false ); + } + return; + } + this._resetButton(); + }, + + refresh: function() { + var isDisabled = this.element.is( ":disabled" ); + if ( isDisabled !== this.options.disabled ) { + this._setOption( "disabled", isDisabled ); + } + if ( this.type === "radio" ) { + radioGroup( this.element[0] ).each(function() { + if ( $( this ).is( ":checked" ) ) { + $( this ).button( "widget" ) + .addClass( "ui-state-active" ) + .attr( "aria-pressed", "true" ); + } else { + $( this ).button( "widget" ) + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + } + }); + } else if ( this.type === "checkbox" ) { + if ( this.element.is( ":checked" ) ) { + this.buttonElement + .addClass( "ui-state-active" ) + .attr( "aria-pressed", "true" ); + } else { + this.buttonElement + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + } + } + }, + + _resetButton: function() { + if ( this.type === "input" ) { + if ( this.options.label ) { + this.element.val( this.options.label ); + } + return; + } + var buttonElement = this.buttonElement.removeClass( typeClasses ), + buttonText = $( "" ) + .addClass( "ui-button-text" ) + .html( this.options.label ) + .appendTo( buttonElement.empty() ) + .text(), + icons = this.options.icons, + multipleIcons = icons.primary && icons.secondary, + buttonClasses = []; + + if ( icons.primary || icons.secondary ) { + if ( this.options.text ) { + buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); + } + + if ( icons.primary ) { + buttonElement.prepend( "" ); + } + + if ( icons.secondary ) { + buttonElement.append( "" ); + } + + if ( !this.options.text ) { + buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); + + if ( !this.hasTitle ) { + buttonElement.attr( "title", buttonText ); + } + } + } else { + buttonClasses.push( "ui-button-text-only" ); + } + buttonElement.addClass( buttonClasses.join( " " ) ); + } +}); + +$.widget( "ui.buttonset", { + options: { + items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" + }, + + _create: function() { + this.element.addClass( "ui-buttonset" ); + }, + + _init: function() { + this.refresh(); + }, + + _setOption: function( key, value ) { + if ( key === "disabled" ) { + this.buttons.button( "option", key, value ); + } + + $.Widget.prototype._setOption.apply( this, arguments ); + }, + + refresh: function() { + var ltr = this.element.css( "direction" ) === "ltr"; + + this.buttons = this.element.find( this.options.items ) + .filter( ":ui-button" ) + .button( "refresh" ) + .end() + .not( ":ui-button" ) + .button() + .end() + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) + .filter( ":first" ) + .addClass( ltr ? "ui-corner-left" : "ui-corner-right" ) + .end() + .filter( ":last" ) + .addClass( ltr ? "ui-corner-right" : "ui-corner-left" ) + .end() + .end(); + }, + + destroy: function() { + this.element.removeClass( "ui-buttonset" ); + this.buttons + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-corner-left ui-corner-right" ) + .end() + .button( "destroy" ); + + $.Widget.prototype.destroy.call( this ); + } +}); + +}( jQuery ) ); +/* + * jQuery UI Dialog 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function( $, undefined ) { + +var uiDialogClasses = + 'ui-dialog ' + + 'ui-widget ' + + 'ui-widget-content ' + + 'ui-corner-all ', + sizeRelatedOptions = { + buttons: true, + height: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + width: true + }, + resizableRelatedOptions = { + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true + }, + // support for jQuery 1.3.2 - handle common attrFn methods for dialog + attrFn = $.attrFn || { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true, + click: true + }; + +$.widget("ui.dialog", { + options: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: 'close', + dialogClass: '', + draggable: true, + hide: null, + height: 'auto', + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: 'center', + at: 'center', + collision: 'fit', + // ensure that the titlebar is never outside the document + using: function(pos) { + var topOffset = $(this).css(pos).offset().top; + if (topOffset < 0) { + $(this).css('top', pos.top - topOffset); + } + } + }, + resizable: true, + show: null, + stack: true, + title: '', + width: 300, + zIndex: 1000 + }, + + _create: function() { + this.originalTitle = this.element.attr('title'); + // #5742 - .attr() might return a DOMElement + if ( typeof this.originalTitle !== "string" ) { + this.originalTitle = ""; + } + + this.options.title = this.options.title || this.originalTitle; + var self = this, + options = self.options, + + title = options.title || ' ', + titleId = $.ui.dialog.getTitleId(self.element), + + uiDialog = (self.uiDialog = $('
                          ')) + .appendTo(document.body) + .hide() + .addClass(uiDialogClasses + options.dialogClass) + .css({ + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + // setting outline to 0 prevents a border on focus in Mozilla + .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { + if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE) { + + self.close(event); + event.preventDefault(); + } + }) + .attr({ + role: 'dialog', + 'aria-labelledby': titleId + }) + .mousedown(function(event) { + self.moveToTop(false, event); + }), + + uiDialogContent = self.element + .show() + .removeAttr('title') + .addClass( + 'ui-dialog-content ' + + 'ui-widget-content') + .appendTo(uiDialog), + + uiDialogTitlebar = (self.uiDialogTitlebar = $('
                          ')) + .addClass( + 'ui-dialog-titlebar ' + + 'ui-widget-header ' + + 'ui-corner-all ' + + 'ui-helper-clearfix' + ) + .prependTo(uiDialog), + + uiDialogTitlebarClose = $('') + .addClass( + 'ui-dialog-titlebar-close ' + + 'ui-corner-all' + ) + .attr('role', 'button') + .hover( + function() { + uiDialogTitlebarClose.addClass('ui-state-hover'); + }, + function() { + uiDialogTitlebarClose.removeClass('ui-state-hover'); + } + ) + .focus(function() { + uiDialogTitlebarClose.addClass('ui-state-focus'); + }) + .blur(function() { + uiDialogTitlebarClose.removeClass('ui-state-focus'); + }) + .click(function(event) { + self.close(event); + return false; + }) + .appendTo(uiDialogTitlebar), + + uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('')) + .addClass( + 'ui-icon ' + + 'ui-icon-closethick' + ) + .text(options.closeText) + .appendTo(uiDialogTitlebarClose), + + uiDialogTitle = $('') + .addClass('ui-dialog-title') + .attr('id', titleId) + .html(title) + .prependTo(uiDialogTitlebar); + + //handling of deprecated beforeclose (vs beforeClose) option + //Ticket #4669 http://dev.jqueryui.com/ticket/4669 + //TODO: remove in 1.9pre + if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { + options.beforeClose = options.beforeclose; + } + + uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); + + if (options.draggable && $.fn.draggable) { + self._makeDraggable(); + } + if (options.resizable && $.fn.resizable) { + self._makeResizable(); + } + + self._createButtons(options.buttons); + self._isOpen = false; + + if ($.fn.bgiframe) { + uiDialog.bgiframe(); + } + }, + + _init: function() { + if ( this.options.autoOpen ) { + this.open(); + } + }, + + destroy: function() { + var self = this; + + if (self.overlay) { + self.overlay.destroy(); + } + self.uiDialog.hide(); + self.element + .unbind('.dialog') + .removeData('dialog') + .removeClass('ui-dialog-content ui-widget-content') + .hide().appendTo('body'); + self.uiDialog.remove(); + + if (self.originalTitle) { + self.element.attr('title', self.originalTitle); + } + + return self; + }, + + widget: function() { + return this.uiDialog; + }, + + close: function(event) { + var self = this, + maxZ, thisZ; + + if (false === self._trigger('beforeClose', event)) { + return; + } + + if (self.overlay) { + self.overlay.destroy(); + } + self.uiDialog.unbind('keypress.ui-dialog'); + + self._isOpen = false; + + if (self.options.hide) { + self.uiDialog.hide(self.options.hide, function() { + self._trigger('close', event); + }); + } else { + self.uiDialog.hide(); + self._trigger('close', event); + } + + $.ui.dialog.overlay.resize(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if (self.options.modal) { + maxZ = 0; + $('.ui-dialog').each(function() { + if (this !== self.uiDialog[0]) { + thisZ = $(this).css('z-index'); + if(!isNaN(thisZ)) { + maxZ = Math.max(maxZ, thisZ); + } + } + }); + $.ui.dialog.maxZ = maxZ; + } + + return self; + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function(force, event) { + var self = this, + options = self.options, + saveScroll; + + if ((options.modal && !force) || + (!options.stack && !options.modal)) { + return self._trigger('focus', event); + } + + if (options.zIndex > $.ui.dialog.maxZ) { + $.ui.dialog.maxZ = options.zIndex; + } + if (self.overlay) { + $.ui.dialog.maxZ += 1; + self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); + } + + //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. + // http://ui.jquery.com/bugs/ticket/3193 + saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; + $.ui.dialog.maxZ += 1; + self.uiDialog.css('z-index', $.ui.dialog.maxZ); + self.element.attr(saveScroll); + self._trigger('focus', event); + + return self; + }, + + open: function() { + if (this._isOpen) { return; } + + var self = this, + options = self.options, + uiDialog = self.uiDialog; + + self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; + self._size(); + self._position(options.position); + uiDialog.show(options.show); + self.moveToTop(true); + + // prevent tabbing out of modal dialogs + if (options.modal) { + uiDialog.bind('keypress.ui-dialog', function(event) { + if (event.keyCode !== $.ui.keyCode.TAB) { + return; + } + + var tabbables = $(':tabbable', this), + first = tabbables.filter(':first'), + last = tabbables.filter(':last'); + + if (event.target === last[0] && !event.shiftKey) { + first.focus(1); + return false; + } else if (event.target === first[0] && event.shiftKey) { + last.focus(1); + return false; + } + }); + } + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + $(self.element.find(':tabbable').get().concat( + uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( + uiDialog.get()))).eq(0).focus(); + + self._isOpen = true; + self._trigger('open'); + + return self; + }, + + _createButtons: function(buttons) { + var self = this, + hasButtons = false, + uiDialogButtonPane = $('
                          ') + .addClass( + 'ui-dialog-buttonpane ' + + 'ui-widget-content ' + + 'ui-helper-clearfix' + ), + uiButtonSet = $( "
                          " ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + // if we already have a button pane, remove it + self.uiDialog.find('.ui-dialog-buttonpane').remove(); + + if (typeof buttons === 'object' && buttons !== null) { + $.each(buttons, function() { + return !(hasButtons = true); + }); + } + if (hasButtons) { + $.each(buttons, function(name, props) { + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + var button = $('') + .click(function() { + props.click.apply(self.element[0], arguments); + }) + .appendTo(uiButtonSet); + // can't use .attr( props, true ) with jQuery 1.3.2. + $.each( props, function( key, value ) { + if ( key === "click" ) { + return; + } + if ( key in attrFn ) { + button[ key ]( value ); + } else { + button.attr( key, value ); + } + }); + if ($.fn.button) { + button.button(); + } + }); + uiDialogButtonPane.appendTo(self.uiDialog); + } + }, + + _makeDraggable: function() { + var self = this, + options = self.options, + doc = $(document), + heightBeforeDrag; + + function filteredUi(ui) { + return { + position: ui.position, + offset: ui.offset + }; + } + + self.uiDialog.draggable({ + cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', + handle: '.ui-dialog-titlebar', + containment: 'document', + start: function(event, ui) { + heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); + $(this).height($(this).height()).addClass("ui-dialog-dragging"); + self._trigger('dragStart', event, filteredUi(ui)); + }, + drag: function(event, ui) { + self._trigger('drag', event, filteredUi(ui)); + }, + stop: function(event, ui) { + options.position = [ui.position.left - doc.scrollLeft(), + ui.position.top - doc.scrollTop()]; + $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); + self._trigger('dragStop', event, filteredUi(ui)); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function(handles) { + handles = (handles === undefined ? this.options.resizable : handles); + var self = this, + options = self.options, + // .ui-resizable has position: relative defined in the stylesheet + // but dialogs have to use absolute or fixed positioning + position = self.uiDialog.css('position'), + resizeHandles = (typeof handles === 'string' ? + handles : + 'n,e,s,w,se,sw,ne,nw' + ); + + function filteredUi(ui) { + return { + originalPosition: ui.originalPosition, + originalSize: ui.originalSize, + position: ui.position, + size: ui.size + }; + } + + self.uiDialog.resizable({ + cancel: '.ui-dialog-content', + containment: 'document', + alsoResize: self.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: self._minHeight(), + handles: resizeHandles, + start: function(event, ui) { + $(this).addClass("ui-dialog-resizing"); + self._trigger('resizeStart', event, filteredUi(ui)); + }, + resize: function(event, ui) { + self._trigger('resize', event, filteredUi(ui)); + }, + stop: function(event, ui) { + $(this).removeClass("ui-dialog-resizing"); + options.height = $(this).height(); + options.width = $(this).width(); + self._trigger('resizeStop', event, filteredUi(ui)); + $.ui.dialog.overlay.resize(); + } + }) + .css('position', position) + .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); + }, + + _minHeight: function() { + var options = this.options; + + if (options.height === 'auto') { + return options.minHeight; + } else { + return Math.min(options.minHeight, options.height); + } + }, + + _position: function(position) { + var myAt = [], + offset = [0, 0], + isVisible; + + if (position) { + // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( + // if (typeof position == 'string' || $.isArray(position)) { + // myAt = $.isArray(position) ? position : position.split(' '); + + if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { + myAt = position.split ? position.split(' ') : [position[0], position[1]]; + if (myAt.length === 1) { + myAt[1] = myAt[0]; + } + + $.each(['left', 'top'], function(i, offsetPosition) { + if (+myAt[i] === myAt[i]) { + offset[i] = myAt[i]; + myAt[i] = offsetPosition; + } + }); + + position = { + my: myAt.join(" "), + at: myAt.join(" "), + offset: offset.join(" ") + }; + } + + position = $.extend({}, $.ui.dialog.prototype.options.position, position); + } else { + position = $.ui.dialog.prototype.options.position; + } + + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is(':visible'); + if (!isVisible) { + this.uiDialog.show(); + } + this.uiDialog + // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 + .css({ top: 0, left: 0 }) + .position($.extend({ of: window }, position)); + if (!isVisible) { + this.uiDialog.hide(); + } + }, + + _setOptions: function( options ) { + var self = this, + resizableOptions = {}, + resize = false; + + $.each( options, function( key, value ) { + self._setOption( key, value ); + + if ( key in sizeRelatedOptions ) { + resize = true; + } + if ( key in resizableRelatedOptions ) { + resizableOptions[ key ] = value; + } + }); + + if ( resize ) { + this._size(); + } + if ( this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", resizableOptions ); + } + }, + + _setOption: function(key, value){ + var self = this, + uiDialog = self.uiDialog; + + switch (key) { + //handling of deprecated beforeclose (vs beforeClose) option + //Ticket #4669 http://dev.jqueryui.com/ticket/4669 + //TODO: remove in 1.9pre + case "beforeclose": + key = "beforeClose"; + break; + case "buttons": + self._createButtons(value); + break; + case "closeText": + // ensure that we always pass a string + self.uiDialogTitlebarCloseText.text("" + value); + break; + case "dialogClass": + uiDialog + .removeClass(self.options.dialogClass) + .addClass(uiDialogClasses + value); + break; + case "disabled": + if (value) { + uiDialog.addClass('ui-dialog-disabled'); + } else { + uiDialog.removeClass('ui-dialog-disabled'); + } + break; + case "draggable": + var isDraggable = uiDialog.is( ":data(draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } + + if ( !isDraggable && value ) { + self._makeDraggable(); + } + break; + case "position": + self._position(value); + break; + case "resizable": + // currently resizable, becoming non-resizable + var isResizable = uiDialog.is( ":data(resizable)" ); + if (isResizable && !value) { + uiDialog.resizable('destroy'); + } + + // currently resizable, changing handles + if (isResizable && typeof value === 'string') { + uiDialog.resizable('option', 'handles', value); + } + + // currently non-resizable, becoming resizable + if (!isResizable && value !== false) { + self._makeResizable(value); + } + break; + case "title": + // convert whatever was passed in o a string, for html() to not throw up + $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); + break; + } + + $.Widget.prototype._setOption.apply(self, arguments); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var options = this.options, + nonContentHeight, + minContentHeight, + isVisible = this.uiDialog.is( ":visible" ); + + // reset content sizing + this.element.show().css({ + width: 'auto', + minHeight: 0, + height: 0 + }); + + if (options.minWidth > options.width) { + options.width = options.minWidth; + } + + // reset wrapper sizing + // determine the height of all the non-content elements + nonContentHeight = this.uiDialog.css({ + height: 'auto', + width: options.width + }) + .height(); + minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); + + if ( options.height === "auto" ) { + // only needed for IE6 support + if ( $.support.minHeight ) { + this.element.css({ + minHeight: minContentHeight, + height: "auto" + }); + } else { + this.uiDialog.show(); + var autoHeight = this.element.css( "height", "auto" ).height(); + if ( !isVisible ) { + this.uiDialog.hide(); + } + this.element.height( Math.max( autoHeight, minContentHeight ) ); + } + } else { + this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + } + + if (this.uiDialog.is(':data(resizable)')) { + this.uiDialog.resizable('option', 'minHeight', this._minHeight()); + } + } +}); + +$.extend($.ui.dialog, { + version: "1.8.16", + + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + var id = $el.attr('id'); + if (!id) { + this.uuid += 1; + id = this.uuid; + } + return 'ui-dialog-title-' + id; + }, + + overlay: function(dialog) { + this.$el = $.ui.dialog.overlay.create(dialog); + } +}); + +$.extend($.ui.dialog.overlay, { + instances: [], + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + oldInstances: [], + maxZ: 0, + events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), + function(event) { return event + '.dialog-overlay'; }).join(' '), + create: function(dialog) { + if (this.instances.length === 0) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ($.ui.dialog.overlay.instances.length) { + $(document).bind($.ui.dialog.overlay.events, function(event) { + // stop events if the z-index of the target is < the z-index of the overlay + // we cannot return true when we don't want to cancel the event (#3523) + if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) { + return false; + } + }); + } + }, 1); + + // allow closing by pressing the escape key + $(document).bind('keydown.dialog-overlay', function(event) { + if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE) { + + dialog.close(event); + event.preventDefault(); + } + }); + + // handle window resize + $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); + } + + var $el = (this.oldInstances.pop() || $('
                          ').addClass('ui-widget-overlay')) + .appendTo(document.body) + .css({ + width: this.width(), + height: this.height() + }); + + if ($.fn.bgiframe) { + $el.bgiframe(); + } + + this.instances.push($el); + return $el; + }, + + destroy: function($el) { + var indexOf = $.inArray($el, this.instances); + if (indexOf != -1){ + this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); + } + + if (this.instances.length === 0) { + $([document, window]).unbind('.dialog-overlay'); + } + + $el.remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + var maxZ = 0; + $.each(this.instances, function() { + maxZ = Math.max(maxZ, this.css('z-index')); + }); + this.maxZ = maxZ; + }, + + height: function() { + var scrollHeight, + offsetHeight; + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if (scrollHeight < offsetHeight) { + return $(window).height() + 'px'; + } else { + return scrollHeight + 'px'; + } + // handle "good" browsers + } else { + return $(document).height() + 'px'; + } + }, + + width: function() { + var scrollWidth, + offsetWidth; + // handle IE + if ( $.browser.msie ) { + scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if (scrollWidth < offsetWidth) { + return $(window).width() + 'px'; + } else { + return scrollWidth + 'px'; + } + // handle "good" browsers + } else { + return $(document).width() + 'px'; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $([]); + $.each($.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add(this); + }); + + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); + } +}); + +$.extend($.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy(this.$el); + } +}); + +}(jQuery)); +/* + * jQuery UI Slider 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) +var numPages = 5; + +$.widget( "ui.slider", $.ui.mouse, { + + widgetEventPrefix: "slide", + + options: { + animate: false, + distance: 0, + max: 100, + min: 0, + orientation: "horizontal", + range: false, + step: 1, + value: 0, + values: null + }, + + _create: function() { + var self = this, + o = this.options, + existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), + handle = "", + handleCount = ( o.values && o.values.length ) || 1, + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass( "ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); + + this.range = $([]); + + if ( o.range ) { + if ( o.range === true ) { + if ( !o.values ) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if ( o.values.length && o.values.length !== 2 ) { + o.values = [ o.values[0], o.values[0] ]; + } + } + + this.range = $( "
                          " ) + .appendTo( this.element ) + .addClass( "ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); + } + + for ( var i = existingHandles.length; i < handleCount; i += 1 ) { + handles.push( handle ); + } + + this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); + + this.handle = this.handles.eq( 0 ); + + this.handles.add( this.range ).filter( "a" ) + .click(function( event ) { + event.preventDefault(); + }) + .hover(function() { + if ( !o.disabled ) { + $( this ).addClass( "ui-state-hover" ); + } + }, function() { + $( this ).removeClass( "ui-state-hover" ); + }) + .focus(function() { + if ( !o.disabled ) { + $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); + $( this ).addClass( "ui-state-focus" ); + } else { + $( this ).blur(); + } + }) + .blur(function() { + $( this ).removeClass( "ui-state-focus" ); + }); + + this.handles.each(function( i ) { + $( this ).data( "index.ui-slider-handle", i ); + }); + + this.handles + .keydown(function( event ) { + var ret = true, + index = $( this ).data( "index.ui-slider-handle" ), + allowed, + curVal, + newVal, + step; + + if ( self.options.disabled ) { + return; + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + ret = false; + if ( !self._keySliding ) { + self._keySliding = true; + $( this ).addClass( "ui-state-active" ); + allowed = self._start( event, index ); + if ( allowed === false ) { + return; + } + } + break; + } + + step = self.options.step; + if ( self.options.values && self.options.values.length ) { + curVal = newVal = self.values( index ); + } else { + curVal = newVal = self.value(); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + newVal = self._valueMin(); + break; + case $.ui.keyCode.END: + newVal = self._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if ( curVal === self._valueMax() ) { + return; + } + newVal = self._trimAlignValue( curVal + step ); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if ( curVal === self._valueMin() ) { + return; + } + newVal = self._trimAlignValue( curVal - step ); + break; + } + + self._slide( event, index, newVal ); + + return ret; + + }) + .keyup(function( event ) { + var index = $( this ).data( "index.ui-slider-handle" ); + + if ( self._keySliding ) { + self._keySliding = false; + self._stop( event, index ); + self._change( event, index ); + $( this ).removeClass( "ui-state-active" ); + } + + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + destroy: function() { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass( "ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" ) + .removeData( "slider" ) + .unbind( ".slider" ); + + this._mouseDestroy(); + + return this; + }, + + _mouseCapture: function( event ) { + var o = this.options, + position, + normValue, + distance, + closestHandle, + self, + index, + allowed, + offset, + mouseOverHandle; + + if ( o.disabled ) { + return false; + } + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x: event.pageX, y: event.pageY }; + normValue = this._normValueFromMouse( position ); + distance = this._valueMax() - this._valueMin() + 1; + self = this; + this.handles.each(function( i ) { + var thisDistance = Math.abs( normValue - self.values(i) ); + if ( distance > thisDistance ) { + distance = thisDistance; + closestHandle = $( this ); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if( o.range === true && this.values(1) === o.min ) { + index += 1; + closestHandle = $( this.handles[index] ); + } + + allowed = this._start( event, index ); + if ( allowed === false ) { + return false; + } + this._mouseSliding = true; + + self._handleIndex = index; + + closestHandle + .addClass( "ui-state-active" ) + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - ( closestHandle.width() / 2 ), + top: event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - + ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) + }; + + if ( !this.handles.hasClass( "ui-state-hover" ) ) { + this._slide( event, index, normValue ); + } + this._animateOff = true; + return true; + }, + + _mouseStart: function( event ) { + return true; + }, + + _mouseDrag: function( event ) { + var position = { x: event.pageX, y: event.pageY }, + normValue = this._normValueFromMouse( position ); + + this._slide( event, this._handleIndex, normValue ); + + return false; + }, + + _mouseStop: function( event ) { + this.handles.removeClass( "ui-state-active" ); + this._mouseSliding = false; + + this._stop( event, this._handleIndex ); + this._change( event, this._handleIndex ); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation: function() { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse: function( position ) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if ( this.orientation === "horizontal" ) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + } + + percentMouse = ( pixelMouse / pixelTotal ); + if ( percentMouse > 1 ) { + percentMouse = 1; + } + if ( percentMouse < 0 ) { + percentMouse = 0; + } + if ( this.orientation === "vertical" ) { + percentMouse = 1 - percentMouse; + } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue( valueMouse ); + }, + + _start: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + return this._trigger( "start", event, uiHash ); + }, + + _slide: function( event, index, newVal ) { + var otherVal, + newValues, + allowed; + + if ( this.options.values && this.options.values.length ) { + otherVal = this.values( index ? 0 : 1 ); + + if ( ( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if ( newVal !== this.values( index ) ) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal, + values: newValues + } ); + otherVal = this.values( index ? 0 : 1 ); + if ( allowed !== false ) { + this.values( index, newVal, true ); + } + } + } else { + if ( newVal !== this.value() ) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal + } ); + if ( allowed !== false ) { + this.value( newVal ); + } + } + } + }, + + _stop: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "stop", event, uiHash ); + }, + + _change: function( event, index ) { + if ( !this._keySliding && !this._mouseSliding ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "change", event, uiHash ); + } + }, + + value: function( newValue ) { + if ( arguments.length ) { + this.options.value = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, 0 ); + return; + } + + return this._value(); + }, + + values: function( index, newValue ) { + var vals, + newValues, + i; + + if ( arguments.length > 1 ) { + this.options.values[ index ] = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, index ); + return; + } + + if ( arguments.length ) { + if ( $.isArray( arguments[ 0 ] ) ) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for ( i = 0; i < vals.length; i += 1 ) { + vals[ i ] = this._trimAlignValue( newValues[ i ] ); + this._change( null, i ); + } + this._refreshValue(); + } else { + if ( this.options.values && this.options.values.length ) { + return this._values( index ); + } else { + return this.value(); + } + } + } else { + return this._values(); + } + }, + + _setOption: function( key, value ) { + var i, + valsLength = 0; + + if ( $.isArray( this.options.values ) ) { + valsLength = this.options.values.length; + } + + $.Widget.prototype._setOption.apply( this, arguments ); + + switch ( key ) { + case "disabled": + if ( value ) { + this.handles.filter( ".ui-state-focus" ).blur(); + this.handles.removeClass( "ui-state-hover" ); + this.handles.propAttr( "disabled", true ); + this.element.addClass( "ui-disabled" ); + } else { + this.handles.propAttr( "disabled", false ); + this.element.removeClass( "ui-disabled" ); + } + break; + case "orientation": + this._detectOrientation(); + this.element + .removeClass( "ui-slider-horizontal ui-slider-vertical" ) + .addClass( "ui-slider-" + this.orientation ); + this._refreshValue(); + break; + case "value": + this._animateOff = true; + this._refreshValue(); + this._change( null, 0 ); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for ( i = 0; i < valsLength; i += 1 ) { + this._change( null, i ); + } + this._animateOff = false; + break; + } + }, + + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value: function() { + var val = this.options.value; + val = this._trimAlignValue( val ); + + return val; + }, + + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values: function( index ) { + var val, + vals, + i; + + if ( arguments.length ) { + val = this.options.values[ index ]; + val = this._trimAlignValue( val ); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for ( i = 0; i < vals.length; i+= 1) { + vals[ i ] = this._trimAlignValue( vals[ i ] ); + } + + return vals; + } + }, + + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function( val ) { + if ( val <= this._valueMin() ) { + return this._valueMin(); + } + if ( val >= this._valueMax() ) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat( alignValue.toFixed(5) ); + }, + + _valueMin: function() { + return this.options.min; + }, + + _valueMax: function() { + return this.options.max; + }, + + _refreshValue: function() { + var oRange = this.options.range, + o = this.options, + self = this, + animate = ( !this._animateOff ) ? o.animate : false, + valPercent, + _set = {}, + lastValPercent, + value, + valueMin, + valueMax; + + if ( this.options.values && this.options.values.length ) { + this.handles.each(function( i, j ) { + valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + if ( self.options.range === true ) { + if ( self.orientation === "horizontal" ) { + if ( i === 0 ) { + self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); + } + if ( i === 1 ) { + self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } else { + if ( i === 0 ) { + self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); + } + if ( i === 1 ) { + self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + lastValPercent = valPercent; + }); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + + if ( oRange === "min" && this.orientation === "horizontal" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "horizontal" ) { + this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + if ( oRange === "min" && this.orientation === "vertical" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "vertical" ) { + this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + +}); + +$.extend( $.ui.slider, { + version: "1.8.16" +}); + +}(jQuery)); +/* + * jQuery UI Tabs 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var tabId = 0, + listId = 0; + +function getNextTabId() { + return ++tabId; +} + +function getNextListId() { + return ++listId; +} + +$.widget( "ui.tabs", { + options: { + add: null, + ajaxOptions: null, + cache: false, + cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + collapsible: false, + disable: null, + disabled: [], + enable: null, + event: "click", + fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } + idPrefix: "ui-tabs-", + load: null, + panelTemplate: "
                          ", + remove: null, + select: null, + show: null, + spinner: "Loading…", + tabTemplate: "
                        • #{label}
                        • " + }, + + _create: function() { + this._tabify( true ); + }, + + _setOption: function( key, value ) { + if ( key == "selected" ) { + if (this.options.collapsible && value == this.options.selected ) { + return; + } + this.select( value ); + } else { + this.options[ key ] = value; + this._tabify(); + } + }, + + _tabId: function( a ) { + return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || + this.options.idPrefix + getNextTabId(); + }, + + _sanitizeSelector: function( hash ) { + // we need this because an id may contain a ":" + return hash.replace( /:/g, "\\:" ); + }, + + _cookie: function() { + var cookie = this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); + return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); + }, + + _ui: function( tab, panel ) { + return { + tab: tab, + panel: panel, + index: this.anchors.index( tab ) + }; + }, + + _cleanup: function() { + // restore all former loading tabs labels + this.lis.filter( ".ui-state-processing" ) + .removeClass( "ui-state-processing" ) + .find( "span:data(label.tabs)" ) + .each(function() { + var el = $( this ); + el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); + }); + }, + + _tabify: function( init ) { + var self = this, + o = this.options, + fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash + + this.list = this.element.find( "ol,ul" ).eq( 0 ); + this.lis = $( " > li:has(a[href])", this.list ); + this.anchors = this.lis.map(function() { + return $( "a", this )[ 0 ]; + }); + this.panels = $( [] ); + + this.anchors.each(function( i, a ) { + var href = $( a ).attr( "href" ); + // For dynamically created HTML that contains a hash as href IE < 8 expands + // such href to the full page url with hash and then misinterprets tab as ajax. + // Same consideration applies for an added tab with a fragment identifier + // since a[href=#fragment-identifier] does unexpectedly not match. + // Thus normalize href attribute... + var hrefBase = href.split( "#" )[ 0 ], + baseEl; + if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || + ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { + href = a.hash; + a.href = href; + } + + // inline tab + if ( fragmentId.test( href ) ) { + self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); + // remote tab + // prevent loading the page itself if href is just "#" + } else if ( href && href !== "#" ) { + // required for restore on destroy + $.data( a, "href.tabs", href ); + + // TODO until #3808 is fixed strip fragment identifier from url + // (IE fails to load from such url) + $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); + + var id = self._tabId( a ); + a.href = "#" + id; + var $panel = self.element.find( "#" + id ); + if ( !$panel.length ) { + $panel = $( o.panelTemplate ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .insertAfter( self.panels[ i - 1 ] || self.list ); + $panel.data( "destroy.tabs", true ); + } + self.panels = self.panels.add( $panel ); + // invalid tab href + } else { + o.disabled.push( i ); + } + }); + + // initialization from scratch + if ( init ) { + // attach necessary classes for styling + this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); + this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); + this.lis.addClass( "ui-state-default ui-corner-top" ); + this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); + + // Selected tab + // use "selected" option or try to retrieve: + // 1. from fragment identifier in url + // 2. from cookie + // 3. from selected class attribute on
                        • + if ( o.selected === undefined ) { + if ( location.hash ) { + this.anchors.each(function( i, a ) { + if ( a.hash == location.hash ) { + o.selected = i; + return false; + } + }); + } + if ( typeof o.selected !== "number" && o.cookie ) { + o.selected = parseInt( self._cookie(), 10 ); + } + if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { + o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + } + o.selected = o.selected || ( this.lis.length ? 0 : -1 ); + } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release + o.selected = -1; + } + + // sanity check - default to first tab... + o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) + ? o.selected + : 0; + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + // A selected tab cannot become disabled. + o.disabled = $.unique( o.disabled.concat( + $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { + return self.lis.index( n ); + }) + ) ).sort(); + + if ( $.inArray( o.selected, o.disabled ) != -1 ) { + o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 ); + } + + // highlight selected tab + this.panels.addClass( "ui-tabs-hide" ); + this.lis.removeClass( "ui-tabs-selected ui-state-active" ); + // check for length avoids error when initializing empty list + if ( o.selected >= 0 && this.anchors.length ) { + self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); + this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); + + // seems to be expected behavior that the show callback is fired + self.element.queue( "tabs", function() { + self._trigger( "show", null, + self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); + }); + + this.load( o.selected ); + } + + // clean up to avoid memory leaks in certain versions of IE 6 + // TODO: namespace this event + $( window ).bind( "unload", function() { + self.lis.add( self.anchors ).unbind( ".tabs" ); + self.lis = self.anchors = self.panels = null; + }); + // update selected after add/remove + } else { + o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + } + + // update collapsible + // TODO: use .toggleClass() + this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); + + // set or update cookie after init and add/remove respectively + if ( o.cookie ) { + this._cookie( o.selected, o.cookie ); + } + + // disable tabs + for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { + $( li )[ $.inArray( i, o.disabled ) != -1 && + // TODO: use .toggleClass() + !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); + } + + // reset cache if switching from cached to not cached + if ( o.cache === false ) { + this.anchors.removeData( "cache.tabs" ); + } + + // remove all handlers before, tabify may run on existing tabs after add or option change + this.lis.add( this.anchors ).unbind( ".tabs" ); + + if ( o.event !== "mouseover" ) { + var addState = function( state, el ) { + if ( el.is( ":not(.ui-state-disabled)" ) ) { + el.addClass( "ui-state-" + state ); + } + }; + var removeState = function( state, el ) { + el.removeClass( "ui-state-" + state ); + }; + this.lis.bind( "mouseover.tabs" , function() { + addState( "hover", $( this ) ); + }); + this.lis.bind( "mouseout.tabs", function() { + removeState( "hover", $( this ) ); + }); + this.anchors.bind( "focus.tabs", function() { + addState( "focus", $( this ).closest( "li" ) ); + }); + this.anchors.bind( "blur.tabs", function() { + removeState( "focus", $( this ).closest( "li" ) ); + }); + } + + // set up animations + var hideFx, showFx; + if ( o.fx ) { + if ( $.isArray( o.fx ) ) { + hideFx = o.fx[ 0 ]; + showFx = o.fx[ 1 ]; + } else { + hideFx = showFx = o.fx; + } + } + + // Reset certain styles left over from animation + // and prevent IE's ClearType bug... + function resetStyle( $el, fx ) { + $el.css( "display", "" ); + if ( !$.support.opacity && fx.opacity ) { + $el[ 0 ].style.removeAttribute( "filter" ); + } + } + + // Show a tab... + var showTab = showFx + ? function( clicked, $show ) { + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way + .animate( showFx, showFx.duration || "normal", function() { + resetStyle( $show, showFx ); + self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); + }); + } + : function( clicked, $show ) { + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + $show.removeClass( "ui-tabs-hide" ); + self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); + }; + + // Hide a tab, $show is optional... + var hideTab = hideFx + ? function( clicked, $hide ) { + $hide.animate( hideFx, hideFx.duration || "normal", function() { + self.lis.removeClass( "ui-tabs-selected ui-state-active" ); + $hide.addClass( "ui-tabs-hide" ); + resetStyle( $hide, hideFx ); + self.element.dequeue( "tabs" ); + }); + } + : function( clicked, $hide, $show ) { + self.lis.removeClass( "ui-tabs-selected ui-state-active" ); + $hide.addClass( "ui-tabs-hide" ); + self.element.dequeue( "tabs" ); + }; + + // attach tab event handler, unbind to avoid duplicates from former tabifying... + this.anchors.bind( o.event + ".tabs", function() { + var el = this, + $li = $(el).closest( "li" ), + $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), + $show = self.element.find( self._sanitizeSelector( el.hash ) ); + + // If tab is already selected and not collapsible or tab disabled or + // or is already loading or click callback returns false stop here. + // Check if click handler returns false last so that it is not executed + // for a disabled or loading tab! + if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || + $li.hasClass( "ui-state-disabled" ) || + $li.hasClass( "ui-state-processing" ) || + self.panels.filter( ":animated" ).length || + self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { + this.blur(); + return false; + } + + o.selected = self.anchors.index( this ); + + self.abort(); + + // if tab may be closed + if ( o.collapsible ) { + if ( $li.hasClass( "ui-tabs-selected" ) ) { + o.selected = -1; + + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + self.element.queue( "tabs", function() { + hideTab( el, $hide ); + }).dequeue( "tabs" ); + + this.blur(); + return false; + } else if ( !$hide.length ) { + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + self.element.queue( "tabs", function() { + showTab( el, $show ); + }); + + // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 + self.load( self.anchors.index( this ) ); + + this.blur(); + return false; + } + } + + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + // show new tab + if ( $show.length ) { + if ( $hide.length ) { + self.element.queue( "tabs", function() { + hideTab( el, $hide ); + }); + } + self.element.queue( "tabs", function() { + showTab( el, $show ); + }); + + self.load( self.anchors.index( this ) ); + } else { + throw "jQuery UI Tabs: Mismatching fragment identifier."; + } + + // Prevent IE from keeping other link focussed when using the back button + // and remove dotted border from clicked link. This is controlled via CSS + // in modern browsers; blur() removes focus from address bar in Firefox + // which can become a usability and annoying problem with tabs('rotate'). + if ( $.browser.msie ) { + this.blur(); + } + }); + + // disable click in any case + this.anchors.bind( "click.tabs", function(){ + return false; + }); + }, + + _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. + // also sanitizes numerical indexes to valid values. + if ( typeof index == "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) ); + } + + return index; + }, + + destroy: function() { + var o = this.options; + + this.abort(); + + this.element + .unbind( ".tabs" ) + .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ) + .removeData( "tabs" ); + + this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); + + this.anchors.each(function() { + var href = $.data( this, "href.tabs" ); + if ( href ) { + this.href = href; + } + var $this = $( this ).unbind( ".tabs" ); + $.each( [ "href", "load", "cache" ], function( i, prefix ) { + $this.removeData( prefix + ".tabs" ); + }); + }); + + this.lis.unbind( ".tabs" ).add( this.panels ).each(function() { + if ( $.data( this, "destroy.tabs" ) ) { + $( this ).remove(); + } else { + $( this ).removeClass([ + "ui-state-default", + "ui-corner-top", + "ui-tabs-selected", + "ui-state-active", + "ui-state-hover", + "ui-state-focus", + "ui-state-disabled", + "ui-tabs-panel", + "ui-widget-content", + "ui-corner-bottom", + "ui-tabs-hide" + ].join( " " ) ); + } + }); + + if ( o.cookie ) { + this._cookie( null, o.cookie ); + } + + return this; + }, + + add: function( url, label, index ) { + if ( index === undefined ) { + index = this.anchors.length; + } + + var self = this, + o = this.options, + $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); + + $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); + + // try to find an existing element before creating a new one + var $panel = self.element.find( "#" + id ); + if ( !$panel.length ) { + $panel = $( o.panelTemplate ) + .attr( "id", id ) + .data( "destroy.tabs", true ); + } + $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); + + if ( index >= this.lis.length ) { + $li.appendTo( this.list ); + $panel.appendTo( this.list[ 0 ].parentNode ); + } else { + $li.insertBefore( this.lis[ index ] ); + $panel.insertBefore( this.panels[ index ] ); + } + + o.disabled = $.map( o.disabled, function( n, i ) { + return n >= index ? ++n : n; + }); + + this._tabify(); + + if ( this.anchors.length == 1 ) { + o.selected = 0; + $li.addClass( "ui-tabs-selected ui-state-active" ); + $panel.removeClass( "ui-tabs-hide" ); + this.element.queue( "tabs", function() { + self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); + }); + + this.load( 0 ); + } + + this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, + + remove: function( index ) { + index = this._getIndex( index ); + var o = this.options, + $li = this.lis.eq( index ).remove(), + $panel = this.panels.eq( index ).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { + this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); + } + + o.disabled = $.map( + $.grep( o.disabled, function(n, i) { + return n != index; + }), + function( n, i ) { + return n >= index ? --n : n; + }); + + this._tabify(); + + this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); + return this; + }, + + enable: function( index ) { + index = this._getIndex( index ); + var o = this.options; + if ( $.inArray( index, o.disabled ) == -1 ) { + return; + } + + this.lis.eq( index ).removeClass( "ui-state-disabled" ); + o.disabled = $.grep( o.disabled, function( n, i ) { + return n != index; + }); + + this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, + + disable: function( index ) { + index = this._getIndex( index ); + var self = this, o = this.options; + // cannot disable already selected tab + if ( index != o.selected ) { + this.lis.eq( index ).addClass( "ui-state-disabled" ); + + o.disabled.push( index ); + o.disabled.sort(); + + this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + + return this; + }, + + select: function( index ) { + index = this._getIndex( index ); + if ( index == -1 ) { + if ( this.options.collapsible && this.options.selected != -1 ) { + index = this.options.selected; + } else { + return this; + } + } + this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); + return this; + }, + + load: function( index ) { + index = this._getIndex( index ); + var self = this, + o = this.options, + a = this.anchors.eq( index )[ 0 ], + url = $.data( a, "load.tabs" ); + + this.abort(); + + // not remote or from cache + if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { + this.element.dequeue( "tabs" ); + return; + } + + // load remote from here on + this.lis.eq( index ).addClass( "ui-state-processing" ); + + if ( o.spinner ) { + var span = $( "span", a ); + span.data( "label.tabs", span.html() ).html( o.spinner ); + } + + this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { + url: url, + success: function( r, s ) { + self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); + + // take care of tab labels + self._cleanup(); + + if ( o.cache ) { + $.data( a, "cache.tabs", true ); + } + + self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); + try { + o.ajaxOptions.success( r, s ); + } + catch ( e ) {} + }, + error: function( xhr, s, e ) { + // take care of tab labels + self._cleanup(); + + self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + o.ajaxOptions.error( xhr, s, index, a ); + } + catch ( e ) {} + } + } ) ); + + // last, so that load event is fired before show... + self.element.dequeue( "tabs" ); + + return this; + }, + + abort: function() { + // stop possibly running animations + this.element.queue( [] ); + this.panels.stop( false, true ); + + // "tabs" queue must not contain more than two elements, + // which are the callbacks for the latest clicked tab... + this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); + + // terminate pending requests from other tabs + if ( this.xhr ) { + this.xhr.abort(); + delete this.xhr; + } + + // take care of tab labels + this._cleanup(); + return this; + }, + + url: function( index, url ) { + this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); + return this; + }, + + length: function() { + return this.anchors.length; + } +}); + +$.extend( $.ui.tabs, { + version: "1.8.16" +}); + +/* + * Tabs Extensions + */ + +/* + * Rotate + */ +$.extend( $.ui.tabs.prototype, { + rotation: null, + rotate: function( ms, continuing ) { + var self = this, + o = this.options; + + var rotate = self._rotate || ( self._rotate = function( e ) { + clearTimeout( self.rotation ); + self.rotation = setTimeout(function() { + var t = o.selected; + self.select( ++t < self.anchors.length ? t : 0 ); + }, ms ); + + if ( e ) { + e.stopPropagation(); + } + }); + + var stop = self._unrotate || ( self._unrotate = !continuing + ? function(e) { + if (e.clientX) { // in case of a true click + self.rotate(null); + } + } + : function( e ) { + t = o.selected; + rotate(); + }); + + // start rotation + if ( ms ) { + this.element.bind( "tabsshow", rotate ); + this.anchors.bind( o.event + ".tabs", stop ); + rotate(); + // stop rotation + } else { + clearTimeout( self.rotation ); + this.element.unbind( "tabsshow", rotate ); + this.anchors.unbind( o.event + ".tabs", stop ); + delete this._rotate; + delete this._unrotate; + } + + return this; + } +}); + +})( jQuery ); +/* + * jQuery UI Datepicker 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker + * + * Depends: + * jquery.ui.core.js + */ +(function( $, undefined ) { + +$.extend($.ui, { datepicker: { version: "1.8.16" } }); + +var PROP_NAME = 'datepicker'; +var dpuuid = new Date().getTime(); +var instActive; + +/* Date picker manager. + Use the singleton instance of this class, $.datepicker, to interact with the date picker. + Settings for (groups of) date pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Datepicker() { + this.debug = false; // Change this to true to start debugging + this._curInst = null; // The current instance in use + this._keyEvent = false; // If the last event was a key event + this._disabledInputs = []; // List of date picker inputs that have been disabled + this._datepickerShowing = false; // True if the popup picker is showing , false if not + this._inDialog = false; // True if showing within a "dialog", false if not + this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division + this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class + this._appendClass = 'ui-datepicker-append'; // The name of the append marker class + this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class + this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class + this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class + this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class + this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class + this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + closeText: 'Done', // Display text for close link + prevText: 'Prev', // Display text for previous month link + nextText: 'Next', // Display text for next month link + currentText: 'Today', // Display text for current month link + monthNames: ['January','February','March','April','May','June', + 'July','August','September','October','November','December'], // Names of months for drop-down and formatting + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting + dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday + weekHeader: 'Wk', // Column header for week of the year + dateFormat: 'mm/dd/yy', // See format options on parseDate + firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... + isRTL: false, // True if right-to-left language, false if left-to-right + showMonthAfterYear: false, // True if the year select precedes month, false for month then year + yearSuffix: '' // Additional text to append to the year in the month headers + }; + this._defaults = { // Global defaults for all the date picker instances + showOn: 'focus', // 'focus' for popup on focus, + // 'button' for trigger button, or 'both' for either + showAnim: 'fadeIn', // Name of jQuery animation for popup + showOptions: {}, // Options for enhanced animations + defaultDate: null, // Used when field is blank: actual date, + // +/-number for offset from today, null for today + appendText: '', // Display text following the input box, e.g. showing the format + buttonText: '...', // Text for trigger button + buttonImage: '', // URL for trigger button image + buttonImageOnly: false, // True if the image appears alone, false if it appears on a button + hideIfNoPrevNext: false, // True to hide next/previous month links + // if not applicable, false to just disable them + navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links + gotoCurrent: false, // True if today link goes back to current selection instead + changeMonth: false, // True if month can be selected directly, false if only prev/next + changeYear: false, // True if year can be selected directly, false if only prev/next + yearRange: 'c-10:c+10', // Range of years to display in drop-down, + // either relative to today's year (-nn:+nn), relative to currently displayed year + // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) + showOtherMonths: false, // True to show dates in other months, false to leave blank + selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable + showWeek: false, // True to show week of the year, false to not show it + calculateWeek: this.iso8601Week, // How to calculate the week of the year, + // takes a Date and returns the number of the week for it + shortYearCutoff: '+10', // Short year values < this are in the current century, + // > this are in the previous century, + // string value starting with '+' for current year + value + minDate: null, // The earliest selectable date, or null for no limit + maxDate: null, // The latest selectable date, or null for no limit + duration: 'fast', // Duration of display/closure + beforeShowDay: null, // Function that takes a date and returns an array with + // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', + // [2] = cell title (optional), e.g. $.datepicker.noWeekends + beforeShow: null, // Function that takes an input field and + // returns a set of custom settings for the date picker + onSelect: null, // Define a callback function when a date is selected + onChangeMonthYear: null, // Define a callback function when the month or year is changed + onClose: null, // Define a callback function when the datepicker is closed + numberOfMonths: 1, // Number of months to show at a time + showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) + stepMonths: 1, // Number of months to step back/forward + stepBigMonths: 12, // Number of months to step back/forward for the big links + altField: '', // Selector for an alternate field to store selected dates into + altFormat: '', // The date format to use for the alternate field + constrainInput: true, // The input is constrained by the current date format + showButtonPanel: false, // True to show button panel, false to not show it + autoSize: false, // True to size the input for the date format, false to leave as is + disabled: false // The initial disabled state + }; + $.extend(this._defaults, this.regional['']); + this.dpDiv = bindHover($('
                          ')); +} + +$.extend(Datepicker.prototype, { + /* Class name added to elements to indicate already configured with a date picker. */ + markerClassName: 'hasDatepicker', + + //Keep track of the maximum number of rows displayed (see #7043) + maxRows: 4, + + /* Debug logging (if enabled). */ + log: function () { + if (this.debug) + console.log.apply('', arguments); + }, + + // TODO rename to "widget" when switching to widget factory + _widgetDatepicker: function() { + return this.dpDiv; + }, + + /* Override the default settings for all instances of the date picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* Attach the date picker to a jQuery selection. + @param target element - the target input field or division or span + @param settings object - the new settings to use for this date picker instance (anonymous) */ + _attachDatepicker: function(target, settings) { + // check for settings on the control itself - in namespace 'date:' + var inlineSettings = null; + for (var attrName in this._defaults) { + var attrValue = target.getAttribute('date:' + attrName); + if (attrValue) { + inlineSettings = inlineSettings || {}; + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + var nodeName = target.nodeName.toLowerCase(); + var inline = (nodeName == 'div' || nodeName == 'span'); + if (!target.id) { + this.uuid += 1; + target.id = 'dp' + this.uuid; + } + var inst = this._newInst($(target), inline); + inst.settings = $.extend({}, settings || {}, inlineSettings || {}); + if (nodeName == 'input') { + this._connectDatepicker(target, inst); + } else if (inline) { + this._inlineDatepicker(target, inst); + } + }, + + /* Create a new instance object. */ + _newInst: function(target, inline) { + var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars + return {id: id, input: target, // associated target + selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection + drawMonth: 0, drawYear: 0, // month being drawn + inline: inline, // is datepicker inline or not + dpDiv: (!inline ? this.dpDiv : // presentation div + bindHover($('
                          ')))}; + }, + + /* Attach the date picker to an input field. */ + _connectDatepicker: function(target, inst) { + var input = $(target); + inst.append = $([]); + inst.trigger = $([]); + if (input.hasClass(this.markerClassName)) + return; + this._attachments(input, inst); + input.addClass(this.markerClassName).keydown(this._doKeyDown). + keypress(this._doKeyPress).keyup(this._doKeyUp). + bind("setData.datepicker", function(event, key, value) { + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key) { + return this._get(inst, key); + }); + this._autoSize(inst); + $.data(target, PROP_NAME, inst); + //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } + }, + + /* Make attachments based on settings. */ + _attachments: function(input, inst) { + var appendText = this._get(inst, 'appendText'); + var isRTL = this._get(inst, 'isRTL'); + if (inst.append) + inst.append.remove(); + if (appendText) { + inst.append = $('' + appendText + ''); + input[isRTL ? 'before' : 'after'](inst.append); + } + input.unbind('focus', this._showDatepicker); + if (inst.trigger) + inst.trigger.remove(); + var showOn = this._get(inst, 'showOn'); + if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field + input.focus(this._showDatepicker); + if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked + var buttonText = this._get(inst, 'buttonText'); + var buttonImage = this._get(inst, 'buttonImage'); + inst.trigger = $(this._get(inst, 'buttonImageOnly') ? + $('').addClass(this._triggerClass). + attr({ src: buttonImage, alt: buttonText, title: buttonText }) : + $('').addClass(this._triggerClass). + html(buttonImage == '' ? buttonText : $('').attr( + { src:buttonImage, alt:buttonText, title:buttonText }))); + input[isRTL ? 'before' : 'after'](inst.trigger); + inst.trigger.click(function() { + if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) + $.datepicker._hideDatepicker(); + else + $.datepicker._showDatepicker(input[0]); + return false; + }); + } + }, + + /* Apply the maximum length for the date format. */ + _autoSize: function(inst) { + if (this._get(inst, 'autoSize') && !inst.inline) { + var date = new Date(2009, 12 - 1, 20); // Ensure double digits + var dateFormat = this._get(inst, 'dateFormat'); + if (dateFormat.match(/[DM]/)) { + var findMax = function(names) { + var max = 0; + var maxI = 0; + for (var i = 0; i < names.length; i++) { + if (names[i].length > max) { + max = names[i].length; + maxI = i; + } + } + return maxI; + }; + date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? + 'monthNames' : 'monthNamesShort')))); + date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? + 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); + } + inst.input.attr('size', this._formatDate(inst, date).length); + } + }, + + /* Attach an inline date picker to a div. */ + _inlineDatepicker: function(target, inst) { + var divSpan = $(target); + if (divSpan.hasClass(this.markerClassName)) + return; + divSpan.addClass(this.markerClassName).append(inst.dpDiv). + bind("setData.datepicker", function(event, key, value){ + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key){ + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + this._setDate(inst, this._getDefaultDate(inst), true); + this._updateDatepicker(inst); + this._updateAlternate(inst); + //If disabled option is true, disable the datepicker before showing it (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } + // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements + // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height + inst.dpDiv.css( "display", "block" ); + }, + + /* Pop-up the date picker in a "dialog" box. + @param input element - ignored + @param date string or Date - the initial date to display + @param onSelect function - the function to call when a date is selected + @param settings object - update the dialog date picker instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen or + event - with x/y coordinates or + leave empty for default (screen centre) + @return the manager object */ + _dialogDatepicker: function(input, date, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + this.uuid += 1; + var id = 'dp' + this.uuid; + this._dialogInput = $(''); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + inst = this._dialogInst = this._newInst(this._dialogInput, false); + inst.settings = {}; + $.data(this._dialogInput[0], PROP_NAME, inst); + } + extendRemove(inst.settings, settings || {}); + date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); + this._dialogInput.val(date); + + this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); + if (!this._pos) { + var browserWidth = document.documentElement.clientWidth; + var browserHeight = document.documentElement.clientHeight; + var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollY = document.documentElement.scrollTop || document.body.scrollTop; + this._pos = // should use actual width/height below + [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; + } + + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); + inst.settings.onSelect = onSelect; + this._inDialog = true; + this.dpDiv.addClass(this._dialogClass); + this._showDatepicker(this._dialogInput[0]); + if ($.blockUI) + $.blockUI(this.dpDiv); + $.data(this._dialogInput[0], PROP_NAME, inst); + return this; + }, + + /* Detach a datepicker from its control. + @param target element - the target input field or division or span */ + _destroyDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + $.removeData(target, PROP_NAME); + if (nodeName == 'input') { + inst.append.remove(); + inst.trigger.remove(); + $target.removeClass(this.markerClassName). + unbind('focus', this._showDatepicker). + unbind('keydown', this._doKeyDown). + unbind('keypress', this._doKeyPress). + unbind('keyup', this._doKeyUp); + } else if (nodeName == 'div' || nodeName == 'span') + $target.removeClass(this.markerClassName).empty(); + }, + + /* Enable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _enableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = false; + inst.trigger.filter('button'). + each(function() { this.disabled = false; }).end(). + filter('img').css({opacity: '1.0', cursor: ''}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().removeClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + removeAttr("disabled"); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + }, + + /* Disable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _disableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = true; + inst.trigger.filter('button'). + each(function() { this.disabled = true; }).end(). + filter('img').css({opacity: '0.5', cursor: 'default'}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().addClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + attr("disabled", "disabled"); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + this._disabledInputs[this._disabledInputs.length] = target; + }, + + /* Is the first field in a jQuery collection disabled as a datepicker? + @param target element - the target input field or division or span + @return boolean - true if disabled, false if enabled */ + _isDisabledDatepicker: function(target) { + if (!target) { + return false; + } + for (var i = 0; i < this._disabledInputs.length; i++) { + if (this._disabledInputs[i] == target) + return true; + } + return false; + }, + + /* Retrieve the instance data for the target control. + @param target element - the target input field or division or span + @return object - the associated instance data + @throws error if a jQuery problem getting data */ + _getInst: function(target) { + try { + return $.data(target, PROP_NAME); + } + catch (err) { + throw 'Missing instance data for this datepicker'; + } + }, + + /* Update or retrieve the settings for a date picker attached to an input field or division. + @param target element - the target input field or division or span + @param name object - the new settings to update or + string - the name of the setting to change or retrieve, + when retrieving also 'all' for all instance settings or + 'defaults' for all global defaults + @param value any - the new value for the setting + (omit if above is an object or to retrieve a value) */ + _optionDatepicker: function(target, name, value) { + var inst = this._getInst(target); + if (arguments.length == 2 && typeof name == 'string') { + return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : + (inst ? (name == 'all' ? $.extend({}, inst.settings) : + this._get(inst, name)) : null)); + } + var settings = name || {}; + if (typeof name == 'string') { + settings = {}; + settings[name] = value; + } + if (inst) { + if (this._curInst == inst) { + this._hideDatepicker(); + } + var date = this._getDateDatepicker(target, true); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + extendRemove(inst.settings, settings); + // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided + if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) + inst.settings.minDate = this._formatDate(inst, minDate); + if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) + inst.settings.maxDate = this._formatDate(inst, maxDate); + this._attachments($(target), inst); + this._autoSize(inst); + this._setDate(inst, date); + this._updateAlternate(inst); + this._updateDatepicker(inst); + } + }, + + // change method deprecated + _changeDatepicker: function(target, name, value) { + this._optionDatepicker(target, name, value); + }, + + /* Redraw the date picker attached to an input field or division. + @param target element - the target input field or division or span */ + _refreshDatepicker: function(target) { + var inst = this._getInst(target); + if (inst) { + this._updateDatepicker(inst); + } + }, + + /* Set the dates for a jQuery selection. + @param target element - the target input field or division or span + @param date Date - the new date */ + _setDateDatepicker: function(target, date) { + var inst = this._getInst(target); + if (inst) { + this._setDate(inst, date); + this._updateDatepicker(inst); + this._updateAlternate(inst); + } + }, + + /* Get the date(s) for the first entry in a jQuery selection. + @param target element - the target input field or division or span + @param noDefault boolean - true if no default date is to be used + @return Date - the current date */ + _getDateDatepicker: function(target, noDefault) { + var inst = this._getInst(target); + if (inst && !inst.inline) + this._setDateFromField(inst, noDefault); + return (inst ? this._getDate(inst) : null); + }, + + /* Handle keystrokes. */ + _doKeyDown: function(event) { + var inst = $.datepicker._getInst(event.target); + var handled = true; + var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); + inst._keyEvent = true; + if ($.datepicker._datepickerShowing) + switch (event.keyCode) { + case 9: $.datepicker._hideDatepicker(); + handled = false; + break; // hide on tab out + case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + + $.datepicker._currentClass + ')', inst.dpDiv); + if (sel[0]) + $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); + var onSelect = $.datepicker._get(inst, 'onSelect'); + if (onSelect) { + var dateStr = $.datepicker._formatDate(inst); + + // trigger custom callback + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); + } + else + $.datepicker._hideDatepicker(); + return false; // don't submit the form + break; // select the value on enter + case 27: $.datepicker._hideDatepicker(); + break; // hide on escape + case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // previous month/year on page up/+ ctrl + case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // next month/year on page down/+ ctrl + case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); + handled = event.ctrlKey || event.metaKey; + break; // clear on ctrl or command +end + case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); + handled = event.ctrlKey || event.metaKey; + break; // current on ctrl or command +home + case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); + handled = event.ctrlKey || event.metaKey; + // -1 day on ctrl or command +left + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +left on Mac + break; + case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // -1 week on ctrl or command +up + case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); + handled = event.ctrlKey || event.metaKey; + // +1 day on ctrl or command +right + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +right + break; + case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // +1 week on ctrl or command +down + default: handled = false; + } + else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home + $.datepicker._showDatepicker(this); + else { + handled = false; + } + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }, + + /* Filter entered characters - based on date format. */ + _doKeyPress: function(event) { + var inst = $.datepicker._getInst(event.target); + if ($.datepicker._get(inst, 'constrainInput')) { + var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); + var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); + } + }, + + /* Synchronise manual entry and field/alternate field. */ + _doKeyUp: function(event) { + var inst = $.datepicker._getInst(event.target); + if (inst.input.val() != inst.lastVal) { + try { + var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + (inst.input ? inst.input.val() : null), + $.datepicker._getFormatConfig(inst)); + if (date) { // only if valid + $.datepicker._setDateFromField(inst); + $.datepicker._updateAlternate(inst); + $.datepicker._updateDatepicker(inst); + } + } + catch (event) { + $.datepicker.log(event); + } + } + return true; + }, + + /* Pop-up the date picker for a given input field. + If false returned from beforeShow event handler do not show. + @param input element - the input field attached to the date picker or + event - if triggered by focus */ + _showDatepicker: function(input) { + input = input.target || input; + if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger + input = $('input', input.parentNode)[0]; + if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here + return; + var inst = $.datepicker._getInst(input); + if ($.datepicker._curInst && $.datepicker._curInst != inst) { + if ( $.datepicker._datepickerShowing ) { + $.datepicker._triggerOnClose($.datepicker._curInst); + } + $.datepicker._curInst.dpDiv.stop(true, true); + } + var beforeShow = $.datepicker._get(inst, 'beforeShow'); + var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; + if(beforeShowSettings === false){ + //false + return; + } + extendRemove(inst.settings, beforeShowSettings); + inst.lastVal = null; + $.datepicker._lastInput = input; + $.datepicker._setDateFromField(inst); + if ($.datepicker._inDialog) // hide cursor + input.value = ''; + if (!$.datepicker._pos) { // position below input + $.datepicker._pos = $.datepicker._findPos(input); + $.datepicker._pos[1] += input.offsetHeight; // add the height + } + var isFixed = false; + $(input).parents().each(function() { + isFixed |= $(this).css('position') == 'fixed'; + return !isFixed; + }); + if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled + $.datepicker._pos[0] -= document.documentElement.scrollLeft; + $.datepicker._pos[1] -= document.documentElement.scrollTop; + } + var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; + $.datepicker._pos = null; + //to avoid flashes on Firefox + inst.dpDiv.empty(); + // determine sizing offscreen + inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); + $.datepicker._updateDatepicker(inst); + // fix width for dynamic number of date pickers + // and adjust position before showing + offset = $.datepicker._checkOffset(inst, offset, isFixed); + inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? + 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', + left: offset.left + 'px', top: offset.top + 'px'}); + if (!inst.inline) { + var showAnim = $.datepicker._get(inst, 'showAnim'); + var duration = $.datepicker._get(inst, 'duration'); + var postProcess = function() { + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !! cover.length ){ + var borders = $.datepicker._getBorders(inst.dpDiv); + cover.css({left: -borders[0], top: -borders[1], + width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); + } + }; + inst.dpDiv.zIndex($(input).zIndex()+1); + $.datepicker._datepickerShowing = true; + if ($.effects && $.effects[showAnim]) + inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); + if (!showAnim || !duration) + postProcess(); + if (inst.input.is(':visible') && !inst.input.is(':disabled')) + inst.input.focus(); + $.datepicker._curInst = inst; + } + }, + + /* Generate the date picker content. */ + _updateDatepicker: function(inst) { + var self = this; + self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) + var borders = $.datepicker._getBorders(inst.dpDiv); + instActive = inst; // for delegate hover events + inst.dpDiv.empty().append(this._generateHTML(inst)); + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 + cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) + } + inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); + var numMonths = this._getNumberOfMonths(inst); + var cols = numMonths[1]; + var width = 17; + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); + if (cols > 1) + inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); + inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + + 'Class']('ui-datepicker-multi'); + inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + + 'Class']('ui-datepicker-rtl'); + if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && + // #6694 - don't focus the input if it's already focused + // this breaks the change event in IE + inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) + inst.input.focus(); + // deffered render of the years select (to avoid flashes on Firefox) + if( inst.yearshtml ){ + var origyearshtml = inst.yearshtml; + setTimeout(function(){ + //assure that inst.yearshtml didn't change. + if( origyearshtml === inst.yearshtml && inst.yearshtml ){ + inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); + } + origyearshtml = inst.yearshtml = null; + }, 0); + } + }, + + /* Retrieve the size of left and top borders for an element. + @param elem (jQuery object) the element of interest + @return (number[2]) the left and top borders */ + _getBorders: function(elem) { + var convert = function(value) { + return {thin: 1, medium: 2, thick: 3}[value] || value; + }; + return [parseFloat(convert(elem.css('border-left-width'))), + parseFloat(convert(elem.css('border-top-width')))]; + }, + + /* Check positioning to remain on screen. */ + _checkOffset: function(inst, offset, isFixed) { + var dpWidth = inst.dpDiv.outerWidth(); + var dpHeight = inst.dpDiv.outerHeight(); + var inputWidth = inst.input ? inst.input.outerWidth() : 0; + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft(); + var viewHeight = document.documentElement.clientHeight + $(document).scrollTop(); + + offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; + + // now check if datepicker is showing outside window viewport - move to a better place if so. + offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? + Math.abs(offset.left + dpWidth - viewWidth) : 0); + offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? + Math.abs(dpHeight + inputHeight) : 0); + + return offset; + }, + + /* Find an object's position on the screen. */ + _findPos: function(obj) { + var inst = this._getInst(obj); + var isRTL = this._get(inst, 'isRTL'); + while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { + obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; + } + var position = $(obj).offset(); + return [position.left, position.top]; + }, + + /* Trigger custom callback of onClose. */ + _triggerOnClose: function(inst) { + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); + }, + + /* Hide the date picker from view. + @param input element - the input field attached to the date picker */ + _hideDatepicker: function(input) { + var inst = this._curInst; + if (!inst || (input && inst != $.data(input, PROP_NAME))) + return; + if (this._datepickerShowing) { + var showAnim = this._get(inst, 'showAnim'); + var duration = this._get(inst, 'duration'); + var postProcess = function() { + $.datepicker._tidyDialog(inst); + this._curInst = null; + }; + if ($.effects && $.effects[showAnim]) + inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : + (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); + if (!showAnim) + postProcess(); + $.datepicker._triggerOnClose(inst); + this._datepickerShowing = false; + this._lastInput = null; + if (this._inDialog) { + this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this.dpDiv); + } + } + this._inDialog = false; + } + }, + + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); + }, + + /* Close date picker if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!$.datepicker._curInst) + return; + var $target = $(event.target); + if ($target[0].id != $.datepicker._mainDivId && + $target.parents('#' + $.datepicker._mainDivId).length == 0 && + !$target.hasClass($.datepicker.markerClassName) && + !$target.hasClass($.datepicker._triggerClass) && + $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI)) + $.datepicker._hideDatepicker(); + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._isDisabledDatepicker(target[0])) { + return; + } + this._adjustInstDate(inst, offset + + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning + period); + this._updateDatepicker(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._get(inst, 'gotoCurrent') && inst.currentDay) { + inst.selectedDay = inst.currentDay; + inst.drawMonth = inst.selectedMonth = inst.currentMonth; + inst.drawYear = inst.selectedYear = inst.currentYear; + } + else { + var date = new Date(); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + } + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var target = $(id); + var inst = this._getInst(target[0]); + inst['selected' + (period == 'M' ? 'Month' : 'Year')] = + inst['draw' + (period == 'M' ? 'Month' : 'Year')] = + parseInt(select.options[select.selectedIndex].value,10); + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a day. */ + _selectDay: function(id, month, year, td) { + var target = $(id); + if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { + return; + } + var inst = this._getInst(target[0]); + inst.selectedDay = inst.currentDay = $('a', td).html(); + inst.selectedMonth = inst.currentMonth = month; + inst.selectedYear = inst.currentYear = year; + this._selectDate(id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + }, + + /* Erase the input field and hide the date picker. */ + _clearDate: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + this._selectDate(target, ''); + }, + + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var target = $(id); + var inst = this._getInst(target[0]); + dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); + if (inst.input) + inst.input.val(dateStr); + this._updateAlternate(inst); + var onSelect = this._get(inst, 'onSelect'); + if (onSelect) + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback + else if (inst.input) + inst.input.trigger('change'); // fire the change event + if (inst.inline) + this._updateDatepicker(inst); + else { + this._hideDatepicker(); + this._lastInput = inst.input[0]; + if (typeof(inst.input[0]) != 'object') + inst.input.focus(); // restore focus + this._lastInput = null; + } + }, + + /* Update any alternate field to synchronise with the main field. */ + _updateAlternate: function(inst) { + var altField = this._get(inst, 'altField'); + if (altField) { // update alternate field too + var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); + var date = this._getDate(inst); + var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); + $(altField).each(function() { $(this).val(dateStr); }); + } + }, + + /* Set as beforeShowDay function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, + + /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + @param date Date - the date to get the week for + @return number - the number of the week within the year that contains this date */ + iso8601Week: function(date) { + var checkDate = new Date(date.getTime()); + // Find Thursday of this week starting on Monday + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + }, + + /* Parse a string value into a date object. + See formatDate below for the possible formats. + + @param format string - the expected format of the date + @param value string - the date in the above format + @param settings Object - attributes include: + shortYearCutoff number - the cutoff year for determining the century (optional) + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return Date - the extracted date value or null if value is blank */ + parseDate: function (format, value, settings) { + if (format == null || value == null) + throw 'Invalid arguments'; + value = (typeof value == 'object' ? value.toString() : value + ''); + if (value == '') + return null; + var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Extract a number from the string value + var getNumber = function(match) { + var isDoubled = lookAhead(match); + var size = (match == '@' ? 14 : (match == '!' ? 20 : + (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); + var digits = new RegExp('^\\d{1,' + size + '}'); + var num = value.substring(iValue).match(digits); + if (!num) + throw 'Missing number at position ' + iValue; + iValue += num[0].length; + return parseInt(num[0], 10); + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames) { + var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { + return [ [k, v] ]; + }).sort(function (a, b) { + return -(a[1].length - b[1].length); + }); + var index = -1; + $.each(names, function (i, pair) { + var name = pair[1]; + if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { + index = pair[0]; + iValue += name.length; + return false; + } + }); + if (index != -1) + return index + 1; + else + throw 'Unknown name at position ' + iValue; + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) != format.charAt(iFormat)) + throw 'Unexpected literal at position ' + iValue; + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + checkLiteral(); + else + switch (format.charAt(iFormat)) { + case 'd': + day = getNumber('d'); + break; + case 'D': + getName('D', dayNamesShort, dayNames); + break; + case 'o': + doy = getNumber('o'); + break; + case 'm': + month = getNumber('m'); + break; + case 'M': + month = getName('M', monthNamesShort, monthNames); + break; + case 'y': + year = getNumber('y'); + break; + case '@': + var date = new Date(getNumber('@')); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case '!': + var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if (lookAhead("'")) + checkLiteral(); + else + literal = true; + break; + default: + checkLiteral(); + } + } + if (iValue < value.length){ + throw "Extra/unparsed characters found in date: " + value.substring(iValue); + } + if (year == -1) + year = new Date().getFullYear(); + else if (year < 100) + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + if (doy > -1) { + month = 1; + day = doy; + do { + var dim = this._getDaysInMonth(year, month - 1); + if (day <= dim) + break; + month++; + day -= dim; + } while (true); + } + var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); + if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) + throw 'Invalid date'; // E.g. 31/02/00 + return date; + }, + + /* Standard date formats. */ + ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) + COOKIE: 'D, dd M yy', + ISO_8601: 'yy-mm-dd', + RFC_822: 'D, d M y', + RFC_850: 'DD, dd-M-y', + RFC_1036: 'D, d M y', + RFC_1123: 'D, d M yy', + RFC_2822: 'D, d M yy', + RSS: 'D, d M y', // RFC 822 + TICKS: '!', + TIMESTAMP: '@', + W3C: 'yy-mm-dd', // ISO 8601 + + _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), + + /* Format a date object into a string value. + The format can be combinations of the following: + d - day of month (no leading zero) + dd - day of month (two digit) + o - day of year (no leading zeros) + oo - day of year (three digit) + D - day name short + DD - day name long + m - month of year (no leading zero) + mm - month of year (two digit) + M - month name short + MM - month name long + y - year (two digit) + yy - year (four digit) + @ - Unix timestamp (ms since 01/01/1970) + ! - Windows ticks (100ns since 01/01/0001) + '...' - literal text + '' - single quote + + @param format string - the desired format of the date + @param date Date - the date value to format + @param settings Object - attributes include: + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return string - the date in the above format */ + formatDate: function (format, date, settings) { + if (!date) + return ''; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Format a number, with leading zero if necessary + var formatNumber = function(match, value, len) { + var num = '' + value; + if (lookAhead(match)) + while (num.length < len) + num = '0' + num; + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (lookAhead(match) ? longNames[value] : shortNames[value]); + }; + var output = ''; + var literal = false; + if (date) + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': + output += formatNumber('d', date.getDate(), 2); + break; + case 'D': + output += formatName('D', date.getDay(), dayNamesShort, dayNames); + break; + case 'o': + output += formatNumber('o', + Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); + break; + case 'm': + output += formatNumber('m', date.getMonth() + 1, 2); + break; + case 'M': + output += formatName('M', date.getMonth(), monthNamesShort, monthNames); + break; + case 'y': + output += (lookAhead('y') ? date.getFullYear() : + (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); + break; + case '@': + output += date.getTime(); + break; + case '!': + output += date.getTime() * 10000 + this._ticksTo1970; + break; + case "'": + if (lookAhead("'")) + output += "'"; + else + literal = true; + break; + default: + output += format.charAt(iFormat); + } + } + return output; + }, + + /* Extract all possible characters from the date format. */ + _possibleChars: function (format) { + var chars = ''; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + for (var iFormat = 0; iFormat < format.length; iFormat++) + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + chars += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': case 'm': case 'y': case '@': + chars += '0123456789'; + break; + case 'D': case 'M': + return null; // Accept anything + case "'": + if (lookAhead("'")) + chars += "'"; + else + literal = true; + break; + default: + chars += format.charAt(iFormat); + } + return chars; + }, + + /* Get a setting value, defaulting if necessary. */ + _get: function(inst, name) { + return inst.settings[name] !== undefined ? + inst.settings[name] : this._defaults[name]; + }, + + /* Parse existing date and initialise date picker. */ + _setDateFromField: function(inst, noDefault) { + if (inst.input.val() == inst.lastVal) { + return; + } + var dateFormat = this._get(inst, 'dateFormat'); + var dates = inst.lastVal = inst.input ? inst.input.val() : null; + var date, defaultDate; + date = defaultDate = this._getDefaultDate(inst); + var settings = this._getFormatConfig(inst); + try { + date = this.parseDate(dateFormat, dates, settings) || defaultDate; + } catch (event) { + this.log(event); + dates = (noDefault ? '' : dates); + } + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + inst.currentDay = (dates ? date.getDate() : 0); + inst.currentMonth = (dates ? date.getMonth() : 0); + inst.currentYear = (dates ? date.getFullYear() : 0); + this._adjustInstDate(inst); + }, + + /* Retrieve the default date shown on opening. */ + _getDefaultDate: function(inst) { + return this._restrictMinMax(inst, + this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); + }, + + /* A date may be specified as an exact value or a relative one. */ + _determineDate: function(inst, date, defaultDate) { + var offsetNumeric = function(offset) { + var date = new Date(); + date.setDate(date.getDate() + offset); + return date; + }; + var offsetString = function(offset) { + try { + return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + offset, $.datepicker._getFormatConfig(inst)); + } + catch (e) { + // Ignore + } + var date = (offset.toLowerCase().match(/^c/) ? + $.datepicker._getDate(inst) : null) || new Date(); + var year = date.getFullYear(); + var month = date.getMonth(); + var day = date.getDate(); + var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var matches = pattern.exec(offset); + while (matches) { + switch (matches[2] || 'd') { + case 'd' : case 'D' : + day += parseInt(matches[1],10); break; + case 'w' : case 'W' : + day += parseInt(matches[1],10) * 7; break; + case 'm' : case 'M' : + month += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + case 'y': case 'Y' : + year += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + } + matches = pattern.exec(offset); + } + return new Date(year, month, day); + }; + var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : + (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); + newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); + if (newDate) { + newDate.setHours(0); + newDate.setMinutes(0); + newDate.setSeconds(0); + newDate.setMilliseconds(0); + } + return this._daylightSavingAdjust(newDate); + }, + + /* Handle switch to/from daylight saving. + Hours may be non-zero on daylight saving cut-over: + > 12 when midnight changeover, but then cannot generate + midnight datetime, so jump to 1AM, otherwise reset. + @param date (Date) the date to check + @return (Date) the corrected date */ + _daylightSavingAdjust: function(date) { + if (!date) return null; + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + }, + + /* Set the date(s) directly. */ + _setDate: function(inst, date, noChange) { + var clear = !date; + var origMonth = inst.selectedMonth; + var origYear = inst.selectedYear; + var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); + inst.selectedDay = inst.currentDay = newDate.getDate(); + inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); + inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); + if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) + this._notifyChange(inst); + this._adjustInstDate(inst); + if (inst.input) { + inst.input.val(clear ? '' : this._formatDate(inst)); + } + }, + + /* Retrieve the date(s) directly. */ + _getDate: function(inst) { + var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + this._daylightSavingAdjust(new Date( + inst.currentYear, inst.currentMonth, inst.currentDay))); + return startDate; + }, + + /* Generate the HTML for the current state of the date picker. */ + _generateHTML: function(inst) { + var today = new Date(); + today = this._daylightSavingAdjust( + new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time + var isRTL = this._get(inst, 'isRTL'); + var showButtonPanel = this._get(inst, 'showButtonPanel'); + var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); + var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); + var numMonths = this._getNumberOfMonths(inst); + var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); + var stepMonths = this._get(inst, 'stepMonths'); + var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); + var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : + new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var drawMonth = inst.drawMonth - showCurrentAtPos; + var drawYear = inst.drawYear; + if (drawMonth < 0) { + drawMonth += 12; + drawYear--; + } + if (maxDate) { + var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), + maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); + maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); + while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { + drawMonth--; + if (drawMonth < 0) { + drawMonth = 11; + drawYear--; + } + } + } + inst.drawMonth = drawMonth; + inst.drawYear = drawYear; + var prevText = this._get(inst, 'prevText'); + prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), + this._getFormatConfig(inst))); + var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? + '' + prevText + '' : + (hideIfNoPrevNext ? '' : '' + prevText + '')); + var nextText = this._get(inst, 'nextText'); + nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), + this._getFormatConfig(inst))); + var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? + '' + nextText + '' : + (hideIfNoPrevNext ? '' : '' + nextText + '')); + var currentText = this._get(inst, 'currentText'); + var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); + currentText = (!navigationAsDateFormat ? currentText : + this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); + var controls = (!inst.inline ? '' : ''); + var buttonPanel = (showButtonPanel) ? '
                          ' + (isRTL ? controls : '') + + (this._isInRange(inst, gotoDate) ? '' : '') + (isRTL ? '' : controls) + '
                          ' : ''; + var firstDay = parseInt(this._get(inst, 'firstDay'),10); + firstDay = (isNaN(firstDay) ? 0 : firstDay); + var showWeek = this._get(inst, 'showWeek'); + var dayNames = this._get(inst, 'dayNames'); + var dayNamesShort = this._get(inst, 'dayNamesShort'); + var dayNamesMin = this._get(inst, 'dayNamesMin'); + var monthNames = this._get(inst, 'monthNames'); + var monthNamesShort = this._get(inst, 'monthNamesShort'); + var beforeShowDay = this._get(inst, 'beforeShowDay'); + var showOtherMonths = this._get(inst, 'showOtherMonths'); + var selectOtherMonths = this._get(inst, 'selectOtherMonths'); + var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; + var defaultDate = this._getDefaultDate(inst); + var html = ''; + for (var row = 0; row < numMonths[0]; row++) { + var group = ''; + this.maxRows = 4; + for (var col = 0; col < numMonths[1]; col++) { + var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); + var cornerClass = ' ui-corner-all'; + var calender = ''; + if (isMultiMonth) { + calender += '
                          '; + } + calender += '
                          ' + + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, + row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers + '
                          ' + + ''; + var thead = (showWeek ? '' : ''); + for (var dow = 0; dow < 7; dow++) { // days of the week + var day = (dow + firstDay) % 7; + thead += '= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + + '' + dayNamesMin[day] + ''; + } + calender += thead + ''; + var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); + if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) + inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; + var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate + var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) + this.maxRows = numRows; + var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); + for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows + calender += ''; + var tbody = (!showWeek ? '' : ''); + for (var dow = 0; dow < 7; dow++) { // create date picker days + var daySettings = (beforeShowDay ? + beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); + var otherMonth = (printDate.getMonth() != drawMonth); + var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + tbody += ''; // display selectable date + printDate.setDate(printDate.getDate() + 1); + printDate = this._daylightSavingAdjust(printDate); + } + calender += tbody + ''; + } + drawMonth++; + if (drawMonth > 11) { + drawMonth = 0; + drawYear++; + } + calender += '
                          ' + this._get(inst, 'weekHeader') + '
                          ' + + this._get(inst, 'calculateWeek')(printDate) + '' + // actions + (otherMonth && !showOtherMonths ? ' ' : // display for other months + (unselectable ? '' + printDate.getDate() + '' : '' + printDate.getDate() + '')) + '
                          ' + (isMultiMonth ? '
                          ' + + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
                          ' : '') : ''); + group += calender; + } + html += group; + } + html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? + '' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
                          '; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ''; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if ( !inst.yearshtml ) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function(value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += ''; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '
                          '; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate: function(inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ +function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.bind('mouseout', function(event) { + var elem = $( event.target ).closest( selector ); + if ( !elem.length ) { + return; + } + elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); + }) + .bind('mouseover', function(event) { + var elem = $( event.target ).closest( selector ); + if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || + !elem.length ) { + return; + } + elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + elem.addClass('ui-state-hover'); + if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); + if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); + }); +} + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Determine whether an object is an array. */ +function isArray(a) { + return (a && (($.browser.safari && typeof a == 'object' && a.length) || + (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if ( !this.length ) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find('body').append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.8.16"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window['DP_jQuery_' + dpuuid] = $; + +})(jQuery); +/* + * jQuery UI Progressbar 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget( "ui.progressbar", { + options: { + value: 0, + max: 100 + }, + + min: 0, + + _create: function() { + this.element + .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .attr({ + role: "progressbar", + "aria-valuemin": this.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this._value() + }); + + this.valueDiv = $( "
                          " ) + .appendTo( this.element ); + + this.oldValue = this._value(); + this._refreshValue(); + }, + + destroy: function() { + this.element + .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + + this.valueDiv.remove(); + + $.Widget.prototype.destroy.apply( this, arguments ); + }, + + value: function( newValue ) { + if ( newValue === undefined ) { + return this._value(); + } + + this._setOption( "value", newValue ); + return this; + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + this.options.value = value; + this._refreshValue(); + if ( this._value() === this.options.max ) { + this._trigger( "complete" ); + } + } + + $.Widget.prototype._setOption.apply( this, arguments ); + }, + + _value: function() { + var val = this.options.value; + // normalize invalid value + if ( typeof val !== "number" ) { + val = 0; + } + return Math.min( this.options.max, Math.max( this.min, val ) ); + }, + + _percentage: function() { + return 100 * this._value() / this.options.max; + }, + + _refreshValue: function() { + var value = this.value(); + var percentage = this._percentage(); + + if ( this.oldValue !== value ) { + this.oldValue = value; + this._trigger( "change" ); + } + + this.valueDiv + .toggle( value > this.min ) + .toggleClass( "ui-corner-right", value === this.options.max ) + .width( percentage.toFixed(0) + "%" ); + this.element.attr( "aria-valuenow", value ); + } +}); + +$.extend( $.ui.progressbar, { + version: "1.8.16" +}); + +})( jQuery ); +/* + * jQuery UI Effects 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */ +;jQuery.effects || (function($, undefined) { + +$.effects = {}; + + + +/******************************************************************************/ +/****************************** COLOR ANIMATIONS ******************************/ +/******************************************************************************/ + +// override the animation for color styles +$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', + 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'], +function(i, attr) { + $.fx.step[attr] = function(fx) { + if (!fx.colorInit) { + fx.start = getColor(fx.elem, attr); + fx.end = getRGB(fx.end); + fx.colorInit = true; + } + + fx.elem.style[attr] = 'rgb(' + + Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' + + Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' + + Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')'; + }; +}); + +// Color Conversion functions from highlightFade +// By Blair Mitchelmore +// http://jquery.offput.ca/highlightFade/ + +// Parse strings looking for color tuples [255,255,255] +function getRGB(color) { + var result; + + // Check if we're already dealing with an array of colors + if ( color && color.constructor == Array && color.length == 3 ) + return color; + + // Look for rgb(num,num,num) + if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) + return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; + + // Look for rgb(num%,num%,num%) + if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) + return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; + + // Look for #a0b1c2 + if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) + return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; + + // Look for #fff + if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) + return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; + + // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 + if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) + return colors['transparent']; + + // Otherwise, we're most likely dealing with a named color + return colors[$.trim(color).toLowerCase()]; +} + +function getColor(elem, attr) { + var color; + + do { + color = $.curCSS(elem, attr); + + // Keep going until we find an element that has color, or we hit the body + if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) + break; + + attr = "backgroundColor"; + } while ( elem = elem.parentNode ); + + return getRGB(color); +}; + +// Some named colors to work with +// From Interface by Stefan Petre +// http://interface.eyecon.ro/ + +var colors = { + aqua:[0,255,255], + azure:[240,255,255], + beige:[245,245,220], + black:[0,0,0], + blue:[0,0,255], + brown:[165,42,42], + cyan:[0,255,255], + darkblue:[0,0,139], + darkcyan:[0,139,139], + darkgrey:[169,169,169], + darkgreen:[0,100,0], + darkkhaki:[189,183,107], + darkmagenta:[139,0,139], + darkolivegreen:[85,107,47], + darkorange:[255,140,0], + darkorchid:[153,50,204], + darkred:[139,0,0], + darksalmon:[233,150,122], + darkviolet:[148,0,211], + fuchsia:[255,0,255], + gold:[255,215,0], + green:[0,128,0], + indigo:[75,0,130], + khaki:[240,230,140], + lightblue:[173,216,230], + lightcyan:[224,255,255], + lightgreen:[144,238,144], + lightgrey:[211,211,211], + lightpink:[255,182,193], + lightyellow:[255,255,224], + lime:[0,255,0], + magenta:[255,0,255], + maroon:[128,0,0], + navy:[0,0,128], + olive:[128,128,0], + orange:[255,165,0], + pink:[255,192,203], + purple:[128,0,128], + violet:[128,0,128], + red:[255,0,0], + silver:[192,192,192], + white:[255,255,255], + yellow:[255,255,0], + transparent: [255,255,255] +}; + + + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ + +var classAnimationActions = ['add', 'remove', 'toggle'], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +function getElementStyles() { + var style = document.defaultView + ? document.defaultView.getComputedStyle(this, null) + : this.currentStyle, + newStyle = {}, + key, + camelCase; + + // webkit enumerates style porperties + if (style && style.length && style[0] && style[style[0]]) { + var len = style.length; + while (len--) { + key = style[len]; + if (typeof style[key] == 'string') { + camelCase = key.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + newStyle[camelCase] = style[key]; + } + } + } else { + for (key in style) { + if (typeof style[key] === 'string') { + newStyle[key] = style[key]; + } + } + } + + return newStyle; +} + +function filterStyles(styles) { + var name, value; + for (name in styles) { + value = styles[name]; + if ( + // ignore null and undefined values + value == null || + // ignore functions (when does this occur?) + $.isFunction(value) || + // shorthand styles that need to be expanded + name in shorthandStyles || + // ignore scrollbars (break in IE) + (/scrollbar/).test(name) || + + // only colors or values that can be converted to numbers + (!(/color/i).test(name) && isNaN(parseFloat(value))) + ) { + delete styles[name]; + } + } + + return styles; +} + +function styleDifference(oldStyle, newStyle) { + var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459 + name; + + for (name in newStyle) { + if (oldStyle[name] != newStyle[name]) { + diff[name] = newStyle[name]; + } + } + + return diff; +} + +$.effects.animateClass = function(value, duration, easing, callback) { + if ($.isFunction(easing)) { + callback = easing; + easing = null; + } + + return this.queue(function() { + var that = $(this), + originalStyleAttr = that.attr('style') || ' ', + originalStyle = filterStyles(getElementStyles.call(this)), + newStyle, + className = that.attr('class'); + + $.each(classAnimationActions, function(i, action) { + if (value[action]) { + that[action + 'Class'](value[action]); + } + }); + newStyle = filterStyles(getElementStyles.call(this)); + that.attr('class', className); + + that.animate(styleDifference(originalStyle, newStyle), { + queue: false, + duration: duration, + easing: easing, + complete: function() { + $.each(classAnimationActions, function(i, action) { + if (value[action]) { that[action + 'Class'](value[action]); } + }); + // work around bug in IE by clearing the cssText before setting it + if (typeof that.attr('style') == 'object') { + that.attr('style').cssText = ''; + that.attr('style').cssText = originalStyleAttr; + } else { + that.attr('style', originalStyleAttr); + } + if (callback) { callback.apply(this, arguments); } + $.dequeue( this ); + } + }); + }); +}; + +$.fn.extend({ + _addClass: $.fn.addClass, + addClass: function(classNames, speed, easing, callback) { + return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); + }, + + _removeClass: $.fn.removeClass, + removeClass: function(classNames,speed,easing,callback) { + return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); + }, + + _toggleClass: $.fn.toggleClass, + toggleClass: function(classNames, force, speed, easing, callback) { + if ( typeof force == "boolean" || force === undefined ) { + if ( !speed ) { + // without speed parameter; + return this._toggleClass(classNames, force); + } else { + return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]); + } + } else { + // without switch parameter; + return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]); + } + }, + + switchClass: function(remove,add,speed,easing,callback) { + return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); + } +}); + + + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +$.extend($.effects, { + version: "1.8.16", + + // Saves a set of properties in a data storage + save: function(element, set) { + for(var i=0; i < set.length; i++) { + if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]); + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function(element, set) { + for(var i=0; i < set.length; i++) { + if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i])); + } + }, + + setMode: function(el, mode) { + if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle + return mode; + }, + + getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value + // this should be a little more flexible in the future to handle a string & hash + var y, x; + switch (origin[0]) { + case 'top': y = 0; break; + case 'middle': y = 0.5; break; + case 'bottom': y = 1; break; + default: y = origin[0] / original.height; + }; + switch (origin[1]) { + case 'left': x = 0; break; + case 'center': x = 0.5; break; + case 'right': x = 1; break; + default: x = origin[1] / original.width; + }; + return {x: x, y: y}; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function(element) { + + // if the element is already wrapped, return it + if (element.parent().is('.ui-effects-wrapper')) { + return element.parent(); + } + + // wrap the element + var props = { + width: element.outerWidth(true), + height: element.outerHeight(true), + 'float': element.css('float') + }, + wrapper = $('
                          ') + .addClass('ui-effects-wrapper') + .css({ + fontSize: '100%', + background: 'transparent', + border: 'none', + margin: 0, + padding: 0 + }), + active = document.activeElement; + + element.wrap(wrapper); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + + wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element + + // transfer positioning properties to the wrapper + if (element.css('position') == 'static') { + wrapper.css({ position: 'relative' }); + element.css({ position: 'relative' }); + } else { + $.extend(props, { + position: element.css('position'), + zIndex: element.css('z-index') + }); + $.each(['top', 'left', 'bottom', 'right'], function(i, pos) { + props[pos] = element.css(pos); + if (isNaN(parseInt(props[pos], 10))) { + props[pos] = 'auto'; + } + }); + element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' }); + } + + return wrapper.css(props).show(); + }, + + removeWrapper: function(element) { + var parent, + active = document.activeElement; + + if (element.parent().is('.ui-effects-wrapper')) { + parent = element.parent().replaceWith(element); + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + return parent; + } + + return element; + }, + + setTransition: function(element, list, factor, value) { + value = value || {}; + $.each(list, function(i, x){ + unit = element.cssUnit(x); + if (unit[0] > 0) value[x] = unit[0] * factor + unit[1]; + }); + return value; + } +}); + + +function _normalizeArguments(effect, options, speed, callback) { + // shift params for method overloading + if (typeof effect == 'object') { + callback = options; + speed = null; + options = effect; + effect = options.effect; + } + if ($.isFunction(options)) { + callback = options; + speed = null; + options = {}; + } + if (typeof options == 'number' || $.fx.speeds[options]) { + callback = speed; + speed = options; + options = {}; + } + if ($.isFunction(speed)) { + callback = speed; + speed = null; + } + + options = options || {}; + + speed = speed || options.duration; + speed = $.fx.off ? 0 : typeof speed == 'number' + ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default; + + callback = callback || options.complete; + + return [effect, options, speed, callback]; +} + +function standardSpeed( speed ) { + // valid standard speeds + if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { + return true; + } + + // invalid strings - treat as "normal" speed + if ( typeof speed === "string" && !$.effects[ speed ] ) { + return true; + } + + return false; +} + +$.fn.extend({ + effect: function(effect, options, speed, callback) { + var args = _normalizeArguments.apply(this, arguments), + // TODO: make effects take actual parameters instead of a hash + args2 = { + options: args[1], + duration: args[2], + callback: args[3] + }, + mode = args2.options.mode, + effectMethod = $.effects[effect]; + + if ( $.fx.off || !effectMethod ) { + // delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args2.duration, args2.callback ); + } else { + return this.each(function() { + if ( args2.callback ) { + args2.callback.call( this ); + } + }); + } + } + + return effectMethod.call(this, args2); + }, + + _show: $.fn.show, + show: function(speed) { + if ( standardSpeed( speed ) ) { + return this._show.apply(this, arguments); + } else { + var args = _normalizeArguments.apply(this, arguments); + args[1].mode = 'show'; + return this.effect.apply(this, args); + } + }, + + _hide: $.fn.hide, + hide: function(speed) { + if ( standardSpeed( speed ) ) { + return this._hide.apply(this, arguments); + } else { + var args = _normalizeArguments.apply(this, arguments); + args[1].mode = 'hide'; + return this.effect.apply(this, args); + } + }, + + // jQuery core overloads toggle and creates _toggle + __toggle: $.fn.toggle, + toggle: function(speed) { + if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { + return this.__toggle.apply(this, arguments); + } else { + var args = _normalizeArguments.apply(this, arguments); + args[1].mode = 'toggle'; + return this.effect.apply(this, args); + } + }, + + // helper functions + cssUnit: function(key) { + var style = this.css(key), val = []; + $.each( ['em','px','%','pt'], function(i, unit){ + if(style.indexOf(unit) > 0) + val = [parseFloat(style), unit]; + }); + return val; + } +}); + + + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +/* + * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ + * + * Uses the built in easing capabilities added In jQuery 1.1 + * to offer multiple easing options + * + * TERMS OF USE - jQuery Easing + * + * Open source under the BSD License. + * + * Copyright 2008 George McGinley Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +// t: current time, b: begInnIng value, c: change In value, d: duration +$.easing.jswing = $.easing.swing; + +$.extend($.easing, +{ + def: 'easeOutQuad', + swing: function (x, t, b, c, d) { + //alert($.easing.default); + return $.easing[$.easing.def](x, t, b, c, d); + }, + easeInQuad: function (x, t, b, c, d) { + return c*(t/=d)*t + b; + }, + easeOutQuad: function (x, t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + easeInOutQuad: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + }, + easeInCubic: function (x, t, b, c, d) { + return c*(t/=d)*t*t + b; + }, + easeOutCubic: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t + 1) + b; + }, + easeInOutCubic: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + }, + easeInQuart: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t + b; + }, + easeOutQuart: function (x, t, b, c, d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + }, + easeInOutQuart: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + }, + easeInQuint: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t*t + b; + }, + easeOutQuint: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t*t*t + 1) + b; + }, + easeInOutQuint: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; + return c/2*((t-=2)*t*t*t*t + 2) + b; + }, + easeInSine: function (x, t, b, c, d) { + return -c * Math.cos(t/d * (Math.PI/2)) + c + b; + }, + easeOutSine: function (x, t, b, c, d) { + return c * Math.sin(t/d * (Math.PI/2)) + b; + }, + easeInOutSine: function (x, t, b, c, d) { + return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; + }, + easeInExpo: function (x, t, b, c, d) { + return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; + }, + easeOutExpo: function (x, t, b, c, d) { + return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; + }, + easeInOutExpo: function (x, t, b, c, d) { + if (t==0) return b; + if (t==d) return b+c; + if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; + return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; + }, + easeInCirc: function (x, t, b, c, d) { + return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; + }, + easeOutCirc: function (x, t, b, c, d) { + return c * Math.sqrt(1 - (t=t/d-1)*t) + b; + }, + easeInOutCirc: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; + return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; + }, + easeInElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + }, + easeOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + }, + easeInOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; + }, + easeInBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*(t/=d)*t*((s+1)*t - s) + b; + }, + easeOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + }, + easeInOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + }, + easeInBounce: function (x, t, b, c, d) { + return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b; + }, + easeOutBounce: function (x, t, b, c, d) { + if ((t/=d) < (1/2.75)) { + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)) { + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)) { + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } + }, + easeInOutBounce: function (x, t, b, c, d) { + if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; + return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; + } +}); + +/* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +})(jQuery); +/* + * jQuery UI Effects Blind 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Blind + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.blind = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'vertical'; // Default direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var ref = (direction == 'vertical') ? 'height' : 'width'; + var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width(); + if(mode == 'show') wrapper.css(ref, 0); // Shift + + // Animation + var animation = {}; + animation[ref] = mode == 'show' ? distance : 0; + + // Animate + wrapper.animate(animation, o.duration, o.options.easing, function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Bounce 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Bounce + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.bounce = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var direction = o.options.direction || 'up'; // Default direction + var distance = o.options.distance || 20; // Default distance + var times = o.options.times || 5; // Default # of times + var speed = o.duration || 250; // Default speed per bounce + if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3); + if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift + if (mode == 'hide') distance = distance / (times * 2); + if (mode != 'hide') times--; + + // Animate + if (mode == 'show') { // Show Bounce + var animation = {opacity: 1}; + animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation, speed / 2, o.options.easing); + distance = distance / 2; + times--; + }; + for (var i = 0; i < times; i++) { // Bounces + var animation1 = {}, animation2 = {}; + animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing); + distance = (mode == 'hide') ? distance * 2 : distance / 2; + }; + if (mode == 'hide') { // Last Bounce + var animation = {opacity: 0}; + animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + el.animate(animation, speed / 2, o.options.easing, function(){ + el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + } else { + var animation1 = {}, animation2 = {}; + animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){ + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + }; + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Clip 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Clip + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.clip = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right','height','width']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'vertical'; // Default direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var animate = el[0].tagName == 'IMG' ? wrapper : el; + var ref = { + size: (direction == 'vertical') ? 'height' : 'width', + position: (direction == 'vertical') ? 'top' : 'left' + }; + var distance = (direction == 'vertical') ? animate.height() : animate.width(); + if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift + + // Animation + var animation = {}; + animation[ref.size] = mode == 'show' ? distance : 0; + animation[ref.position] = mode == 'show' ? 0 : distance / 2; + + // Animate + animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Drop 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Drop + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.drop = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right','opacity']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'left'; // Default Direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2); + if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift + + // Animation + var animation = {opacity: mode == 'show' ? 1 : 0}; + animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Explode 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Explode + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.explode = function(o) { + + return this.queue(function() { + + var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + + o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode; + var el = $(this).show().css('visibility', 'hidden'); + var offset = el.offset(); + + //Substract the margins - not fixing the problem yet. + offset.top -= parseInt(el.css("marginTop"),10) || 0; + offset.left -= parseInt(el.css("marginLeft"),10) || 0; + + var width = el.outerWidth(true); + var height = el.outerHeight(true); + + for(var i=0;i
      ') + .css({ + position: 'absolute', + visibility: 'visible', + left: -j*(width/cells), + top: -i*(height/rows) + }) + .parent() + .addClass('ui-effects-explode') + .css({ + position: 'absolute', + overflow: 'hidden', + width: width/cells, + height: height/rows, + left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0), + top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0), + opacity: o.options.mode == 'show' ? 0 : 1 + }).animate({ + left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)), + top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)), + opacity: o.options.mode == 'show' ? 1 : 0 + }, o.duration || 500); + } + } + + // Set a timeout, to call the callback approx. when the other animations have finished + setTimeout(function() { + + o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide(); + if(o.callback) o.callback.apply(el[0]); // Callback + el.dequeue(); + + $('div.ui-effects-explode').remove(); + + }, o.duration || 500); + + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Fade 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.fade = function(o) { + return this.queue(function() { + var elem = $(this), + mode = $.effects.setMode(elem, o.options.mode || 'hide'); + + elem.animate({ opacity: mode }, { + queue: false, + duration: o.duration, + easing: o.options.easing, + complete: function() { + (o.callback && o.callback.apply(this, arguments)); + elem.dequeue(); + } + }); + }); +}; + +})(jQuery); +/* + * jQuery UI Effects Fold 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.fold = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var size = o.options.size || 15; // Default fold size + var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value + var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var widthFirst = ((mode == 'show') != horizFirst); + var ref = widthFirst ? ['width', 'height'] : ['height', 'width']; + var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()]; + var percent = /([0-9]+)%/.exec(size); + if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1]; + if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift + + // Animation + var animation1 = {}, animation2 = {}; + animation1[ref[0]] = mode == 'show' ? distance[0] : size; + animation2[ref[1]] = mode == 'show' ? distance[1] : 0; + + // Animate + wrapper.animate(animation1, duration, o.options.easing) + .animate(animation2, duration, o.options.easing, function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Highlight 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.highlight = function(o) { + return this.queue(function() { + var elem = $(this), + props = ['backgroundImage', 'backgroundColor', 'opacity'], + mode = $.effects.setMode(elem, o.options.mode || 'show'), + animation = { + backgroundColor: elem.css('backgroundColor') + }; + + if (mode == 'hide') { + animation.opacity = 0; + } + + $.effects.save(elem, props); + elem + .show() + .css({ + backgroundImage: 'none', + backgroundColor: o.options.color || '#ffff99' + }) + .animate(animation, { + queue: false, + duration: o.duration, + easing: o.options.easing, + complete: function() { + (mode == 'hide' && elem.hide()); + $.effects.restore(elem, props); + (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); + (o.callback && o.callback.apply(this, arguments)); + elem.dequeue(); + } + }); + }); +}; + +})(jQuery); +/* + * jQuery UI Effects Pulsate 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.pulsate = function(o) { + return this.queue(function() { + var elem = $(this), + mode = $.effects.setMode(elem, o.options.mode || 'show'); + times = ((o.options.times || 5) * 2) - 1; + duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2, + isVisible = elem.is(':visible'), + animateTo = 0; + + if (!isVisible) { + elem.css('opacity', 0).show(); + animateTo = 1; + } + + if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) { + times--; + } + + for (var i = 0; i < times; i++) { + elem.animate({ opacity: animateTo }, duration, o.options.easing); + animateTo = (animateTo + 1) % 2; + } + + elem.animate({ opacity: animateTo }, duration, o.options.easing, function() { + if (animateTo == 0) { + elem.hide(); + } + (o.callback && o.callback.apply(this, arguments)); + }); + + elem + .queue('fx', function() { elem.dequeue(); }) + .dequeue(); + }); +}; + +})(jQuery); +/* + * jQuery UI Effects Scale 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Scale + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.puff = function(o) { + return this.queue(function() { + var elem = $(this), + mode = $.effects.setMode(elem, o.options.mode || 'hide'), + percent = parseInt(o.options.percent, 10) || 150, + factor = percent / 100, + original = { height: elem.height(), width: elem.width() }; + + $.extend(o.options, { + fade: true, + mode: mode, + percent: mode == 'hide' ? percent : 100, + from: mode == 'hide' + ? original + : { + height: original.height * factor, + width: original.width * factor + } + }); + + elem.effect('scale', o.options, o.duration, o.callback); + elem.dequeue(); + }); +}; + +$.effects.scale = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this); + + // Set options + var options = $.extend(true, {}, o.options); + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent + var direction = o.options.direction || 'both'; // Set default axis + var origin = o.options.origin; // The origin of the scaling + if (mode != 'effect') { // Set default origin and restore for show/hide + options.origin = origin || ['middle','center']; + options.restore = true; + } + var original = {height: el.height(), width: el.width()}; // Save original + el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state + + // Adjust + var factor = { // Set scaling factor + y: direction != 'horizontal' ? (percent / 100) : 1, + x: direction != 'vertical' ? (percent / 100) : 1 + }; + el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state + + if (o.options.fade) { // Fade option to support puff + if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;}; + if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;}; + }; + + // Animation + options.from = el.from; options.to = el.to; options.mode = mode; + + // Animate + el.effect('size', options, o.duration, o.callback); + el.dequeue(); + }); + +}; + +$.effects.size = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity']; + var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore + var props2 = ['width','height','overflow']; // Copy for children + var cProps = ['fontSize']; + var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; + var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var restore = o.options.restore || false; // Default restore + var scale = o.options.scale || 'both'; // Default scale mode + var origin = o.options.origin; // The origin of the sizing + var original = {height: el.height(), width: el.width()}; // Save original + el.from = o.options.from || original; // Default from state + el.to = o.options.to || original; // Default to state + // Adjust + if (origin) { // Calculate baseline shifts + var baseline = $.effects.getBaseline(origin, original); + el.from.top = (original.height - el.from.height) * baseline.y; + el.from.left = (original.width - el.from.width) * baseline.x; + el.to.top = (original.height - el.to.height) * baseline.y; + el.to.left = (original.width - el.to.width) * baseline.x; + }; + var factor = { // Set scaling factor + from: {y: el.from.height / original.height, x: el.from.width / original.width}, + to: {y: el.to.height / original.height, x: el.to.width / original.width} + }; + if (scale == 'box' || scale == 'both') { // Scale the css box + if (factor.from.y != factor.to.y) { // Vertical props scaling + props = props.concat(vProps); + el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from); + el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to); + }; + if (factor.from.x != factor.to.x) { // Horizontal props scaling + props = props.concat(hProps); + el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from); + el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to); + }; + }; + if (scale == 'content' || scale == 'both') { // Scale the content + if (factor.from.y != factor.to.y) { // Vertical props scaling + props = props.concat(cProps); + el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from); + el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to); + }; + }; + $.effects.save(el, restore ? props : props1); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + el.css('overflow','hidden').css(el.from); // Shift + + // Animate + if (scale == 'content' || scale == 'both') { // Scale the children + vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size + hProps = hProps.concat(['marginLeft','marginRight']); // Add margins + props2 = props.concat(vProps).concat(hProps); // Concat + el.find("*[width]").each(function(){ + child = $(this); + if (restore) $.effects.save(child, props2); + var c_original = {height: child.height(), width: child.width()}; // Save original + child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x}; + child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x}; + if (factor.from.y != factor.to.y) { // Vertical props scaling + child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from); + child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to); + }; + if (factor.from.x != factor.to.x) { // Horizontal props scaling + child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from); + child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to); + }; + child.css(child.from); // Shift children + child.animate(child.to, o.duration, o.options.easing, function(){ + if (restore) $.effects.restore(child, props2); // Restore children + }); // Animate children + }); + }; + + // Animate + el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if (el.to.opacity === 0) { + el.css('opacity', el.from.opacity); + } + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Shake 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Shake + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.shake = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var direction = o.options.direction || 'left'; // Default direction + var distance = o.options.distance || 20; // Default distance + var times = o.options.times || 3; // Default # of times + var speed = o.duration || o.options.duration || 140; // Default speed per shake + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + + // Animation + var animation = {}, animation1 = {}, animation2 = {}; + animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2; + animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2; + + // Animate + el.animate(animation, speed, o.options.easing); + for (var i = 1; i < times; i++) { // Shakes + el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing); + }; + el.animate(animation1, speed, o.options.easing). + animate(animation, speed / 2, o.options.easing, function(){ // Last shake + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Slide 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Slide + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.slide = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode + var direction = o.options.direction || 'left'; // Default Direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true})); + if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift + + // Animation + var animation = {}; + animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Transfer 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Transfer + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.transfer = function(o) { + return this.queue(function() { + var elem = $(this), + target = $(o.options.to), + endPosition = target.offset(), + animation = { + top: endPosition.top, + left: endPosition.left, + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = elem.offset(), + transfer = $('
      ') + .appendTo(document.body) + .addClass(o.options.className) + .css({ + top: startPosition.top, + left: startPosition.left, + height: elem.innerHeight(), + width: elem.innerWidth(), + position: 'absolute' + }) + .animate(animation, o.duration, o.options.easing, function() { + transfer.remove(); + (o.callback && o.callback.apply(elem[0], arguments)); + elem.dequeue(); + }); + }); +}; + +})(jQuery); diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery-ui.min.js b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery-ui.min.js new file mode 100644 index 0000000..a6660d6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery-ui.min.js @@ -0,0 +1,791 @@ +/*! + * jQuery UI 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.16", +keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({propAttr:c.fn.prop||c.fn.attr,_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d= +this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this, +"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart": +"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight, +outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a, +"tabindex"),d=isNaN(b);return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&& +a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted= +false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +;/* + * jQuery UI Position 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */ +(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.setTimeout){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j={top:b.of.pageY, +left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/2;if(b.at[1]==="bottom")j.top+= +k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+(parseInt(c.curCSS(this,"marginRight",true))||0),w=m+q+(parseInt(c.curCSS(this,"marginBottom",true))||0),i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]==="center")i.top-= +m/2;i.left=Math.round(i.left);i.top=Math.round(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();b.left= +d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= +a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), +g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;if(b.iframeFix)d(b.iframeFix===true?"iframe":b.iframeFix).each(function(){d('
      ').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")});return true},_mouseStart:function(a){var b=this.options; +this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}); +this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);d.ui.ddmanager&&d.ui.ddmanager.dragStart(this,a);return true}, +_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b= +false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration, +10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},_mouseUp:function(a){this.options.iframeFix===true&&d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});d.ui.ddmanager&&d.ui.ddmanager.dragStop(this,a);return d.ui.mouse.prototype._mouseUp.call(this,a)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle|| +!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone().removeAttr("id"):this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&& +a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent= +this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"), +10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"), +10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[a.containment=="document"?0:d(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,a.containment=="document"?0:d(window).scrollTop()-this.offset.relative.top-this.offset.parent.top, +(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){a=d(a.containment);var b=a[0];if(b){a.offset();var c=d(b).css("overflow")!= +"hidden";this.containment=[(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"), +10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=a}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+ +this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&& +!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,h=a.pageY;if(this.originalPosition){var g;if(this.containment){if(this.relative_container){g=this.relative_container.offset();g=[this.containment[0]+g.left,this.containment[1]+g.top,this.containment[2]+g.left,this.containment[3]+g.top]}else g=this.containment;if(a.pageX-this.offset.click.leftg[2])e=g[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>g[3])h=g[3]+this.offset.click.top}if(b.grid){h=b.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/b.grid[1])*b.grid[1]:this.originalPageY;h=g?!(h-this.offset.click.topg[3])?h:!(h-this.offset.click.topg[2])?e:!(e-this.offset.click.left=0;i--){var j=c.snapElements[i].left,l=j+c.snapElements[i].width,k=c.snapElements[i].top,m=k+c.snapElements[i].height;if(j-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>= +i&&e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){if(!a.disabled){e(this).removeClass("ui-resizable-autohide");b._handles.show()}},function(){if(!a.disabled)if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy(); +var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a= +false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"}); +this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff= +{width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis]; +if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false}, +_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;f=f?0:c.sizeDiff.width;f={width:c.helper.width()-f,height:c.helper.height()-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f, +{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",b);this._helper&&this.helper.remove();return false},_updateVirtualBoundaries:function(b){var a=this.options,c,d,f;a={minWidth:k(a.minWidth)?a.minWidth:0,maxWidth:k(a.maxWidth)?a.maxWidth:Infinity,minHeight:k(a.minHeight)?a.minHeight:0,maxHeight:k(a.maxHeight)?a.maxHeight: +Infinity};if(this._aspectRatio||b){b=a.minHeight*this.aspectRatio;d=a.minWidth/this.aspectRatio;c=a.maxHeight*this.aspectRatio;f=a.maxWidth/this.aspectRatio;if(b>a.minWidth)a.minWidth=b;if(d>a.minHeight)a.minHeight=d;if(cb.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&l)b.left=i-a.minWidth;if(d&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left= +null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+ +a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+ +c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]); +b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,{version:"1.8.16"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(), +10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top- +f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var l=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:l.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(l.css("position"))){c._revertToRelativePosition=true;l.css({position:"absolute",top:"auto",left:"auto"})}l.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType? +e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a= +e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing, +step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= +e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top","Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset; +var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left: +a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top- +d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition, +f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, +display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b= +e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height= +d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +;/* + * jQuery UI Selectable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), +selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
      ")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, +c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting", +c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d= +this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a=== +"disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&& +!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top, +left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]}; +this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!= +document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a); +return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0], +e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset(); +c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"): +this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null, +dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")}, +toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith(); +if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), +this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b];if(!(c.instance!=this.currentContainer&&this.currentContainer&&c.item[0]!=this.currentItem[0])){var e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b= +this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f= +d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")|| +0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out", +a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h- +f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g- +this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this, +this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop", +a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); +a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); +if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var h=d.closest(".ui-accordion-header");a.active=h.length?h:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion", +function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a= +this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"); +this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons(); +b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,h=this.headers.index(a.target),f=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:f=this.headers[(h+1)%d];break;case b.LEFT:case b.UP:f=this.headers[(h-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target); +a.preventDefault()}if(f){c(a.target).attr("tabIndex",-1);c(f).attr("tabIndex",0);f.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+ +c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options; +if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){var h=this.active;j=a.next();g=this.active.next();e={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):j,oldContent:g};var f=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(j,g,e,b,f);h.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);a.next().addClass("ui-accordion-content-active")}}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var g=this.active.next(), +e={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:g},j=this.active=c([]);this._toggle(j,g,e)}},_toggle:function(a,b,d,h,f){var g=this,e=g.options;g.toShow=a;g.toHide=b;g.data=d;var j=function(){if(g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data);g.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&h?{toShow:c([]),toHide:b,complete:j,down:f,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:f,autoHeight:e.autoHeight|| +e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;h=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!h[k]&&!c.easing[k])k="slide";h[k]||(h[k]=function(l){this.slide(l,{easing:k,duration:i||700})});h[k](d)}else{if(e.collapsible&&h)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false", +"aria-selected":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.16", +animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/); +f[i]={value:j[1],unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide", +paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.propAttr("readOnly"))){g= +false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= +a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)}; +this.menu=d("
        ").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&& +a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); +d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&& +b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source= +this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(d("").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, +"\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery); +(function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b, +this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.first()?":last":":first"))},hasScroll:function(){return this.element.height()").addClass("ui-button-text").html(this.options.label).appendTo(a.empty()).text(),e=this.options.icons,f=e.primary&&e.secondary,d=[];if(e.primary||e.secondary){if(this.options.text)d.push("ui-button-text-icon"+(f?"s":e.primary?"-primary":"-secondary"));e.primary&&a.prepend("");e.secondary&&a.append("");if(!this.options.text){d.push(f?"ui-button-icons-only": +"ui-button-icon-only");this.hasTitle||a.attr("title",c)}}else d.push("ui-button-text-only");a.addClass(d.join(" "))}}});b.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(a,c){a==="disabled"&&this.buttons.button("option",a,c);b.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var a=this.element.css("direction")=== +"ltr";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(a?"ui-corner-left":"ui-corner-right").end().filter(":last").addClass(a?"ui-corner-right":"ui-corner-left").end().end()},destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"); +b.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, +position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
        ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ +b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&!i.isDefaultPrevented()&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
        ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), +h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", +e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); +a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== +b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()};c.ui.dialog.maxZ+=1; +d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== +f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
        ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
        ").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, +function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", +handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, +originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", +f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): +[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); +if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): +e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= +this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- +b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.16",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), +create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&& +c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(b.range==="min"||b.range==="max"?" ui-slider-range-"+b.range:""))}for(var j=c.length;j"); +this.handles=c.add(d(e.join("")).appendTo(a.element));this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(g){g.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(g){d(this).data("index.ui-slider-handle", +g)});this.handles.keydown(function(g){var k=true,l=d(this).data("index.ui-slider-handle"),i,h,m;if(!a.options.disabled){switch(g.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:k=false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");i=a._start(g,l);if(i===false)return}break}m=a.options.step;i=a.options.values&&a.options.values.length? +(h=a.values(l)):(h=a.value());switch(g.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(i+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(i-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(i===a._valueMax())return;h=a._trimAlignValue(i+m);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(i===a._valueMin())return;h=a._trimAlignValue(i- +m);break}a._slide(g,l,h);return k}}).keyup(function(g){var k=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(g,k);a._change(g,k);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy(); +return this},_mouseCapture:function(a){var b=this.options,c,f,e,j,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});f=this._valueMax()-this._valueMin()+1;j=this;this.handles.each(function(k){var l=Math.abs(c-j.values(k));if(f>l){f=l;e=d(this);g=k}});if(b.range===true&&this.values(1)===b.min){g+=1;e=d(this.handles[g])}if(this._start(a,g)===false)return false; +this._mouseSliding=true;j._handleIndex=g;e.addClass("ui-state-active").focus();b=e.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-e.width()/2,top:a.pageY-b.top-e.height()/2-(parseInt(e.css("borderTopWidth"),10)||0)-(parseInt(e.css("borderBottomWidth"),10)||0)+(parseInt(e.css("marginTop"),10)||0)};this.handles.hasClass("ui-state-hover")||this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b= +this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b= +this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b); +c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var f;if(this.options.values&&this.options.values.length){f=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>f||b===1&&c1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}else if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;f=arguments[0];for(e=0;e=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,f=!this._animateOff?b.animate:false,e,j={},g,k,l,i;if(this.options.values&&this.options.values.length)this.handles.each(function(h){e=(c.values(h)-c._valueMin())/(c._valueMax()-c._valueMin())*100;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";d(this).stop(1,1)[f?"animate":"css"](j,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(h===0)c.range.stop(1,1)[f?"animate":"css"]({left:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({width:e- +g+"%"},{queue:false,duration:b.animate})}else{if(h===0)c.range.stop(1,1)[f?"animate":"css"]({bottom:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({height:e-g+"%"},{queue:false,duration:b.animate})}g=e});else{k=this.value();l=this._valueMin();i=this._valueMax();e=i!==l?(k-l)/(i-l)*100:0;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[f?"animate":"css"](j,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[f?"animate":"css"]({width:e+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[f?"animate":"css"]({width:100-e+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[f?"animate":"css"]({height:e+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[f?"animate":"css"]({height:100-e+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.16"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
        ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
      • #{label}
      • "},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& +e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= +d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]|| +(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a.element.find(a._sanitizeSelector(i)));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=a.element.find("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(c.selected>=0&&this.anchors.length){a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash))[0]))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); +this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+ +g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal", +function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")}; +this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=a.element.find(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected= +-1;c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; +d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e= +d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b, +e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=c.element.find("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]); +j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove(); +if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null, +this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this}, +load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){e.element.find(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c, +"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this}, +url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.16"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k'))}function N(a){return a.bind("mouseout", +function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");b.length&&b.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");if(!(d.datepicker._isDisabledDatepicker(J.inline?a.parent()[0]:J.input[0])||!b.length)){b.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); +b.addClass("ui-state-hover");b.hasClass("ui-datepicker-prev")&&b.addClass("ui-datepicker-prev-hover");b.hasClass("ui-datepicker-next")&&b.addClass("ui-datepicker-next-hover")}})}function H(a,b){d.extend(a,b);for(var c in b)if(b[c]==null||b[c]==C)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.16"}});var B=(new Date).getTime(),J;d.extend(M.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv}, +setDefaults:function(a){H(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g, +"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:N(d('
        '))}},_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker", +function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b);b.settings.disabled&&this._disableDatepicker(a)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c== +"focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f==""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker(): +d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a, +b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),true);this._updateDatepicker(b);this._updateAlternate(b);b.settings.disabled&&this._disableDatepicker(a);b.dpDiv.css("display","block")}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+= +1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}H(a.settings,e||{});b=b&&b.constructor==Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/ +2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e= +a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().removeClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=d(a),c=d.data(a, +"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().addClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f== +a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input", +a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);if(d.datepicker._curInst&&d.datepicker._curInst!=b){d.datepicker._datepickerShowing&&d.datepicker._triggerOnClose(d.datepicker._curInst);d.datepicker._curInst.dpDiv.stop(true,true)}var c=d.datepicker._get(b,"beforeShow");c=c?c.apply(a,[a,b]):{};if(c!==false){H(b.settings,c);b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value= +"";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b); +c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.datepicker._datepickerShowing= +true;d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}}},_updateDatepicker:function(a){this.maxRows=4;var b=d.datepicker._getBorders(a.dpDiv);J=a;a.dpDiv.empty().append(this._generateHTML(a));var c=a.dpDiv.find("iframe.ui-datepicker-cover");c.length&&c.css({left:-b[0],top:-b[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}); +a.dpDiv.find("."+this._dayOverClass+" a").mouseover();b=this._getNumberOfMonths(a);c=b[1];a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");c>1&&a.dpDiv.addClass("ui-datepicker-multi-"+c).css("width",17*c+"em");a.dpDiv[(b[0]!=1||b[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&& +!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var e=a.yearshtml;setTimeout(function(){e===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);e=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(), +h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b= +this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_triggerOnClose:function(a){var b=this._get(a,"onClose");if(b)b.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a])},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b); +this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();d.datepicker._triggerOnClose(b);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")}, +_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"): +0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e["selected"+(c=="M"? +"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a); +this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField"); +if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"? +b.toString():b+"";if(b=="")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=A+1-1){j=1;l=u;do{e=this._getDaysInMonth(c,j-1);if(l<=e)break;j++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,j-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=j||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd", +COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames: +null)||this._defaults.monthNames;var i=function(o){(o=k+1 +12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||a.input&& +a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),j=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay? +new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),k=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=k&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-j,1)),this._getFormatConfig(a)); +n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var s=this._get(a,"nextText");s=!h?s:this.formatDate(s,this._daylightSavingAdjust(new Date(m, +g+j,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+s+"":f?"":''+s+"";j=this._get(a,"currentText");s=this._get(a,"gotoCurrent")&& +a.currentDay?u:b;j=!h?j:this.formatDate(j,s,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
        '+(c?h:"")+(this._isInRange(a,s)?'":"")+(c?"":h)+"
        ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;j=this._get(a,"showWeek");s=this._get(a,"dayNames");this._get(a,"dayNamesShort");var q=this._get(a,"dayNamesMin"),A=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),D=this._get(a,"showOtherMonths"),K=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var E=this._getDefaultDate(a),w="",x=0;x1)switch(G){case 0:y+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:y+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:y+=" ui-datepicker-group-middle";t="";break}y+='">'}y+='
        '+(/all|left/.test(t)&& +x==0?c?f:n:"")+(/all|right/.test(t)&&x==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,x>0||G>0,A,v)+'
        ';var z=j?'":"";for(t=0;t<7;t++){var r=(t+h)%7;z+="=5?' class="ui-datepicker-week-end"':"")+'>'+q[r]+""}y+=z+"";z=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +z);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;z=Math.ceil((t+z)/7);this.maxRows=z=l?this.maxRows>z?this.maxRows:z:z;r=this._daylightSavingAdjust(new Date(m,g,1-t));for(var Q=0;Q";var R=!j?"":'";for(t=0;t<7;t++){var I=p?p.apply(a.input?a.input[0]:null,[r]):[true,""],F=r.getMonth()!=g,L=F&&!K||!I[0]||k&&ro;R+='";r.setDate(r.getDate()+1);r=this._daylightSavingAdjust(r)}y+=R+""}g++;if(g>11){g=0;m++}y+="
        '+this._get(a,"weekHeader")+"
        '+this._get(a,"calculateWeek")(r)+""+(F&&!D?" ":L?''+ +r.getDate()+"":''+r.getDate()+"")+"
        "+(l?""+(i[0]>0&&G==i[1]-1?'
        ':""):"");O+=y}w+=O}w+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return w},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='
        ',o="";if(h||!j)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(k+=o+(h||!(j&&l)?" ":""));if(!a.yearshtml){a.yearshtml="";if(h||!l)k+=''+c+"";else{g=this._get(a,"yearRange").split(":");var s=(new Date).getFullYear();i=function(q){q=q.match(/c[+-].*/)?c+parseInt(q.substring(1),10):q.match(/[+-].*/)?s+parseInt(q,10):parseInt(q,10);return isNaN(q)?s:q};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b, +e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='";k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?" ":"")+o;k+="
        ";return k},_adjustInstDate:function(a,b,c){var e=a.drawYear+(c=="Y"?b:0),f=a.drawMonth+ +(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");if(b)b.apply(a.input? +a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);c=this._daylightSavingAdjust(new Date(c, +e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a, +"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=function(a){if(!this.length)return this; +if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));return this.each(function(){typeof a== +"string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new M;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.16";window["DP_jQuery_"+B]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("
        ").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===d)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){if(a==="value"){this.options.value=c;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100* +this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.16"})})(jQuery); +;/* + * jQuery UI Effects 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */ +jQuery.effects||function(f,j){function m(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return n.transparent;return n[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return m(b)}function o(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function p(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:b in f.fx.speeds?f.fx.speeds[b]:f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function l(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor", +"borderTopColor","borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=m(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var n={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0, +0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211, +211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},q=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b, +d){if(f.isFunction(b)){d=b;b=null}return this.queue(function(){var e=f(this),g=e.attr("style")||" ",h=p(o.call(this)),r,v=e.attr("class");f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});r=p(o.call(this));e.attr("class",v);e.animate(u(h,r),{queue:false,duration:a,easing:b,complete:function(){f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments);f.dequeue(this)}})})}; +f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this, +[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.16",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}), +d=document.activeElement;c.wrap(b);if(c[0]===d||f.contains(c[0],d))f(d).focus();b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(e,g){a[g]=c.css(g);if(isNaN(parseInt(a[g],10)))a[g]="auto"});c.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return b.css(a).show()},removeWrapper:function(c){var a,b=document.activeElement; +if(c.parent().is(".ui-effects-wrapper")){a=c.parent().replaceWith(c);if(c[0]===b||f.contains(c[0],b))f(b).focus();return a}return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)}); +return d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this, +arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/ +2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b, +d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c, +a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b, +d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fade 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1], +10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; diff --git a/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery.js b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery.js new file mode 100644 index 0000000..8ccd0ea --- /dev/null +++ b/vendor/ruby/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts/jquery.js @@ -0,0 +1,9266 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!memory; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + marginDiv, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
        a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = marginDiv = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + conMarginTop, ptlm, vb, style, html, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; + vb = "visibility:hidden;border:0;"; + style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; + html = "
        " + + "" + + "
        "; + + container = document.createElement("div"); + container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
        t
        "; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Figure out if the W3C box model works as expected + div.innerHTML = ""; + div.style.width = div.style.paddingLeft = "1px"; + jQuery.boxModel = support.boxModel = div.offsetWidth === 2; + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
        "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.style.cssText = ptlm + vb; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + body.removeChild( container ); + div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, attr, name, + data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { + attr = this[0].attributes; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + jQuery._data( this[0], "parsedAttrs", true ); + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var self = jQuery( this ), + args = [ parts[0], value ]; + + self.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + + // See #9699 for explanation of this approach (setting first, then removal) + jQuery.attr( elem, name, "" ); + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /\bhover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Determine handlers that should run if there are delegated events + // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on.call( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

        "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
        "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
        ", "
        " ], + thead: [ 1, "", "
        " ], + tr: [ 2, "", "
        " ], + td: [ 3, "", "
        " ], + col: [ 2, "", "
        " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + +

        Fetching object from server

        +
        + Wait...
        + +
        + + + diff --git a/vendor/ruby/1.9.1/gems/json-1.6.5/data/prototype.js b/vendor/ruby/1.9.1/gems/json-1.6.5/data/prototype.js new file mode 100644 index 0000000..5c73462 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/json-1.6.5/data/prototype.js @@ -0,0 +1,4184 @@ +/* Prototype JavaScript framework, version 1.6.0 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.0', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, + MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + document.createElement('div').__proto__ && + document.createElement('div').__proto__ !== + document.createElement('form').__proto__ + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + +if (Prototype.Browser.WebKit) + Prototype.BrowserFeatures.XPath = false; + +/* Based on Alex Arnell's inheritance implementation. */ +var Class = { + create: function() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + var subclass = function() { }; + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + + return klass; + } +}; + +Class.Methods = { + addMethods: function(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) + properties.push("toString", "valueOf"); + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value, value = Object.extend((function(m) { + return function() { return ancestor[m].apply(this, arguments) }; + })(property).wrap(method), { + valueOf: function() { return method }, + toString: function() { return method.toString() } + }); + } + this.prototype[property] = value; + } + + return this; + } +}; + +var Abstract = { }; + +Object.extend = function(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; +}; + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (Object.isElement(object)) return; + + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + }, + + toQueryString: function(object) { + return $H(object).toQueryString(); + }, + + toHTML: function(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({ }, object); + }, + + isElement: function(object) { + return object && object.nodeType == 1; + }, + + isArray: function(object) { + return object && object.constructor === Array; + }, + + isHash: function(object) { + return object instanceof Hash; + }, + + isFunction: function(object) { + return typeof object == "function"; + }, + + isString: function(object) { + return typeof object == "string"; + }, + + isNumber: function(object) { + return typeof object == "number"; + }, + + isUndefined: function(object) { + return typeof object == "undefined"; + } +}); + +Object.extend(Function.prototype, { + argumentNames: function() { + var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); + return names.length == 1 && !names[0] ? [] : names; + }, + + bind: function() { + if (arguments.length < 2 && arguments[0] === undefined) return this; + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } + }, + + bindAsEventListener: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } + }, + + curry: function() { + if (!arguments.length) return this; + var __method = this, args = $A(arguments); + return function() { + return __method.apply(this, args.concat($A(arguments))); + } + }, + + delay: function() { + var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + }, + + wrap: function(wrapper) { + var __method = this; + return function() { + return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + } + }, + + methodize: function() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + return __method.apply(null, [this].concat($A(arguments))); + }; + } +}); + +Function.prototype.defer = Function.prototype.delay.curry(0.01); + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + } finally { + this.currentlyExecuting = false; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = new Element('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + isJSON: function() { + var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + }, + + interpolate: function(object, pattern) { + return new Template(this, pattern).evaluate(object); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +}; + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return ''; + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }.bind(this)); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = { + each: function(iterator, context) { + var index = 0; + iterator = iterator.bind(context); + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + }, + + all: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function(iterator, context) { + iterator = iterator.bind(context); + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator, context) { + iterator = iterator.bind(context); + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(filter, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(filter); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator(value, index)); + }); + return results; + }, + + include: function(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator, context) { + iterator = iterator.bind(context); + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result; + this.each(function(value, index) { + value = iterator(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result; + this.each(function(value, index) { + value = iterator(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator, context) { + iterator = iterator.bind(context); + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator, context) { + iterator = iterator.bind(context); + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +}; + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + filter: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray, + every: Enumerable.all, + some: Enumerable.any +}); +function $A(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + var length = iterable.length, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +if (Prototype.Browser.WebKit) { + function $A(iterable) { + if (!iterable) return []; + if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && + iterable.toArray) return iterable.toArray(); + var length = iterable.length, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; + } +} + +Array.from = $A; + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(Object.isArray(value) ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + intersect: function(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +// use native browser JS 1.6 implementation if available +if (Object.isFunction(Array.prototype.forEach)) + Array.prototype._each = Array.prototype.forEach; + +if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; +}; + +if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; +}; + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (Object.isArray(arguments[i])) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + }; +} +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +$w('abs round ceil floor').each(function(method){ + Number.prototype[method] = Math[method].methodize(); +}); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; + }()) { + function each(iterator) { + var cache = []; + for (var key in this._object) { + var value = this._object[key]; + if (cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + } else { + function each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + return { + initialize: function(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + }, + + _each: each, + + set: function(key, value) { + return this._object[key] = value; + }, + + get: function(key) { + return this._object[key]; + }, + + unset: function(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + }, + + toObject: function() { + return Object.clone(this._object); + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + index: function(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + }, + + merge: function(object) { + return this.clone().update(object); + }, + + update: function(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + }, + + toQueryString: function() { + return this.map(function(pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return values.map(toQueryPair.curry(key)).join('&'); + } + return toQueryPair(key, values); + }).join('&'); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Object.toJSON(this.toObject()); + }, + + clone: function() { + return new Hash(this); + } + } +})()); + +Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; +Hash.from = $H; +var ObjectRange = Class.create(Enumerable, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +}; + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); + +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + } +}); + +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = xml === undefined ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json'))) + return null; + try { + return this.transport.responseText.evalJSON(options.sanitizeJSON); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = options || { }; + var onComplete = options.onComplete; + options.onComplete = (function(response, param) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, param); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + + if (this.success()) { + if (this.onComplete) this.onComplete.bind(this).defer(); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + // DOM level 2 ECMAScript Language Binding + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + +(function() { + var element = this.Element; + this.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (Prototype.Browser.IE && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(this.Element, element || { }); +}).call(window); + +Element.cache = { }; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + content = Object.toHTML(content); + element.innerHTML = content.stripScripts(); + content.evalScripts.bind(content).defer(); + return element; + }, + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, t, range; + + for (position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + t = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + t.insert(element, content); + continue; + } + + content = Object.toHTML(content); + + range = element.ownerDocument.createRange(); + t.initializeRange(element, range); + t.insert(element, range.createContextualFragment(content.stripScripts())); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + select: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + adjacent: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = element.readAttribute('id'), self = arguments.callee; + if (id) return id; + do { id = 'anonymous_element_' + self.counter++ } while ($(id)); + element.writeAttribute('id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = value === undefined ? true : value; + + for (var attr in attributes) { + var name = t.names[attr] || attr, value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!element.hasClassName(className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return element[element.hasClassName(className) ? + 'removeClassName' : 'addClassName'](className); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (element.sourceIndex && !Prototype.Browser.Opera) { + var e = element.sourceIndex, a = ancestor.sourceIndex, + nextAncestor = ancestor.nextSibling; + if (!nextAncestor) { + do { ancestor = ancestor.parentNode; } + while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); + } + if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); + } + + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = element.cumulativeOffset(); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (element.getStyle('position') == 'absolute') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + var offsets = element.positionedOffset(); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (element.getStyle('position') == 'relative') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || element.tagName == 'BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + // find page position of source + source = $(source); + var p = source.viewportOffset(); + + // find coordinate system to use + element = $(element); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(element, 'position') == 'absolute') { + parent = element.getOffsetParent(); + delta = parent.viewportOffset(); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Element.Methods.identify.counter = 1; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + + +if (!document.createRange || Prototype.Browser.Opera) { + Element.Methods.insert = function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = { bottom: insertions }; + + var t = Element._insertionTranslations, content, position, pos, tagName; + + for (position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + pos = t[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + pos.insert(element, content); + continue; + } + + content = Object.toHTML(content); + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + if (t.tags[tagName]) { + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + if (position == 'top' || position == 'after') fragments.reverse(); + fragments.each(pos.insert.curry(element)); + } + else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); + + content.evalScripts.bind(content).defer(); + } + + return element; + }; +} + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; + Element.Methods._readAttribute = Element.Methods.readAttribute; + Element.Methods.readAttribute = function(element, attribute) { + if (attribute == 'title') return element.title; + return Element._readAttribute(element, attribute); + }; +} + +else if (Prototype.Browser.IE) { + $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + var position = element.getStyle('position'); + if (position != 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset' + style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = { + read: { + names: { + 'class': 'className', + 'for': 'htmlFor' + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: function(element, attribute) { + var attribute = element.getAttribute(attribute); + return attribute ? attribute.toString().slice(23, -2) : null; + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + }; + + Element._attributeTranslations.write = { + names: Object.clone(Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr, + src: v._getAttr, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + // Safari returns margins on body which is incorrect if the child is absolutely + // positioned. For performance reasons, redefine Position.cumulativeOffset for + // KHTML/WebKit only. + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if (Prototype.Browser.IE || Prototype.Browser.Opera) { + // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements + Element.Methods.update = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + + content = Object.toHTML(content); + var tagName = element.tagName.toUpperCase(); + + if (tagName in Element._insertionTranslations.tags) { + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { element.appendChild(node) }); + } + else element.innerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +if (document.createElement('div').outerHTML) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: { + adjacency: 'beforeBegin', + insert: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + initializeRange: function(element, range) { + range.setStartBefore(element); + } + }, + top: { + adjacency: 'afterBegin', + insert: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + initializeRange: function(element, range) { + range.selectNodeContents(element); + range.collapse(true); + } + }, + bottom: { + adjacency: 'beforeEnd', + insert: function(element, node) { + element.appendChild(node); + } + }, + after: { + adjacency: 'afterEnd', + insert: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + initializeRange: function(element, range) { + range.setStartAfter(element); + } + }, + tags: { + TABLE: ['', '
        ', 1], + TBODY: ['', '
        ', 2], + TR: ['', '
        ', 3], + TD: ['
        ', '
        ', 4], + SELECT: ['', 1] + } +}; + +(function() { + this.bottom.initializeRange = this.top.initializeRange; + Object.extend(this.tags, { + THEAD: this.tags.TBODY, + TFOOT: this.tags.TBODY, + TH: this.tags.TD + }); +}).call(Element._insertionTranslations); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = { }; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.extend = (function() { + if (Prototype.BrowserFeatures.SpecificElementExtensions) + return Prototype.K; + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || element._extendedByPrototype || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName, property, value; + + // extend methods for specific tags + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + for (property in methods) { + value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + // extend methods for all tags (Safari doesn't need this) + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || { }); + else { + if (Object.isArray(tagName)) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = { }; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = { }; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + +document.viewport = { + getDimensions: function() { + var dimensions = { }; + $w('width height').each(function(d) { + var D = d.capitalize(); + dimensions[d] = self['inner' + D] || + (document.documentElement['client' + D] || document.body['client' + D]); + }); + return dimensions; + }, + + getWidth: function() { + return this.getDimensions().width; + }, + + getHeight: function() { + return this.getDimensions().height; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + this.tokens = []; + + var e = this.expression, ps = Selector.patterns, as = Selector.assertions; + var le, p, m; + + while (e && le !== e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + // use the Selector.assertions methods unless the selector + // is too complex. + if (as[i]) { + this.tokens.push([i, Object.clone(m)]); + e = e.replace(m[0], ''); + } else { + // reluctantly do a document-wide search + // and look for a match in the array + return this.findElements(document).include(element); + } + } + } + } + + var match = true, name, matches; + for (var i = 0, token; token = this.tokens[i]; i++) { + name = token[0], matches = token[1]; + if (!Selector.assertions[name](element, matches)) { + match = false; break; + } + } + + return match; + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}); + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + // for Selector.match and Element#match + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return Selector.operators[matches[2]](nodeValue, matches[3]); + } + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!targetNode) return []; + if (!nodes && root == document) return [targetNode]; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (options.hash === undefined) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + // a key is already present; construct an array of values + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (value === undefined) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (value === undefined) return element.value; + else element.value = value; + }, + + select: function(element, index) { + if (index === undefined) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, value, single = !Object.isArray(index); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + value = this.optionValue(opt); + if (single) { + if (value == index) { + opt.selected = true; + return; + } + } + else opt.selected = index.include(value); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) var Event = { }; + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: { }, + + relatedTarget: function(event) { + var element; + switch(event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } +}); + +Event.Methods = (function() { + var isButton; + + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + isButton = function(event, code) { + return event.button == buttonMap[code]; + }; + + } else if (Prototype.Browser.WebKit) { + isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + + } else { + isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + return { + isLeftClick: function(event) { return isButton(event, 0) }, + isMiddleClick: function(event) { return isButton(event, 1) }, + isRightClick: function(event) { return isButton(event, 2) }, + + element: function(event) { + var node = Event.extend(event).target; + return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); + }, + + findElement: function(event, expression) { + var element = Event.element(event); + return element.match(expression) ? element : element.up(expression); + }, + + pointer: function(event) { + return { + x: event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)), + y: event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)) + }; + }, + + pointerX: function(event) { return Event.pointer(event).x }, + pointerY: function(event) { return Event.pointer(event).y }, + + stop: function(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + event.stopped = true; + } + }; +})(); + +Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return "[object Event]" } + }); + + return function(event) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + Object.extend(event, { + target: event.srcElement, + relatedTarget: Event.relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + return Object.extend(event, methods); + }; + + } else { + Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; + Object.extend(Event.prototype, methods); + return Prototype.K; + } +})(); + +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._eventID) return element._eventID; + arguments.callee.id = arguments.callee.id || 1; + return element._eventID = ++arguments.callee.id; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event) + }; + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + if (document.createEvent) { + var event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + var event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return event; + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards and John Resig. */ + + var timer, fired = false; + + function fireContentLoadedEvent() { + if (fired) return; + if (timer) window.clearInterval(timer); + document.fire("dom:loaded"); + fired = true; + } + + if (document.addEventListener) { + if (Prototype.Browser.WebKit) { + timer = window.setInterval(function() { + if (/loaded|complete/.test(document.readyState)) + fireContentLoadedEvent(); + }, 0); + + Event.observe(window, "load", fireContentLoadedEvent); + + } else { + document.addEventListener("DOMContentLoaded", + fireContentLoadedEvent, false); + } + + } else { + document.write(" + + + +
        +

        <%=h exception.class %> at <%=h path %>

        +

        <%=h exception.message %>

        + + + + + + +
        Ruby +<% if first = frames.first %> + <%=h first.filename %>: in <%=h first.function %>, line <%=h frames.first.lineno %> +<% else %> + unknown location +<% end %> +
        Web<%=h req.request_method %> <%=h(req.host + path)%>
        + +

        Jump to:

        + +
        + +
        +

        Traceback (innermost first)

        +
          +<% frames.each { |frame| %> +
        • + <%=h frame.filename %>: in <%=h frame.function %> + + <% if frame.context_line %> +
          + <% if frame.pre_context %> +
            + <% frame.pre_context.each { |line| %> +
          1. <%=h line %>
          2. + <% } %> +
          + <% end %> + +
            +
          1. <%=h frame.context_line %>...
          + + <% if frame.post_context %> +
            + <% frame.post_context.each { |line| %> +
          1. <%=h line %>
          2. + <% } %> +
          + <% end %> +
          + <% end %> +
        • +<% } %> +
        +
        + +
        +

        Request information

        + +

        GET

        + <% if req.GET and not req.GET.empty? %> + + + + + + + + + <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %> + + + + + <% } %> + +
        VariableValue
        <%=h key %>
        <%=h val.inspect %>
        + <% else %> +

        No GET data.

        + <% end %> + +

        POST

        + <% if req.POST and not req.POST.empty? %> + + + + + + + + + <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %> + + + + + <% } %> + +
        VariableValue
        <%=h key %>
        <%=h val.inspect %>
        + <% else %> +

        No POST data.

        + <% end %> + + + + <% unless req.cookies.empty? %> + + + + + + + + + <% req.cookies.each { |key, val| %> + + + + + <% } %> + +
        VariableValue
        <%=h key %>
        <%=h val.inspect %>
        + <% else %> +

        No cookie data.

        + <% end %> + +

        Rack ENV

        + + + + + + + + + <% env.sort_by { |k, v| k.to_s }.each { |key, val| %> + + + + + <% } %> + +
        VariableValue
        <%=h key %>
        <%=h val %>
        + +
        + +
        +

        + You're seeing this error because you use Rack::ShowExceptions. +

        +
        + + + +HTML + + # :startdoc: + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/showstatus.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/showstatus.rb new file mode 100644 index 0000000..e1fff99 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/showstatus.rb @@ -0,0 +1,113 @@ +require 'erb' +require 'rack/request' +require 'rack/utils' + +module Rack + # Rack::ShowStatus catches all empty responses the app it wraps and + # replaces them with a site explaining the error. + # + # Additional details can be put into rack.showstatus.detail + # and will be shown as HTML. If such details exist, the error page + # is always rendered, even if the reply was not empty. + + class ShowStatus + def initialize(app) + @app = app + @template = ERB.new(TEMPLATE) + end + + def call(env) + status, headers, body = @app.call(env) + headers = Utils::HeaderHash.new(headers) + empty = headers['Content-Length'].to_i <= 0 + + # client or server error, or explicit message + if (status.to_i >= 400 && empty) || env["rack.showstatus.detail"] + # This double assignment is to prevent an "unused variable" warning on + # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me. + req = req = Rack::Request.new(env) + + message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s + + # This double assignment is to prevent an "unused variable" warning on + # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me. + detail = detail = env["rack.showstatus.detail"] || message + + body = @template.result(binding) + size = Rack::Utils.bytesize(body) + [status, headers.merge("Content-Type" => "text/html", "Content-Length" => size.to_s), [body]] + else + [status, headers, body] + end + end + + def h(obj) # :nodoc: + case obj + when String + Utils.escape_html(obj) + else + Utils.escape_html(obj.inspect) + end + end + + # :stopdoc: + +# adapted from Django +# Copyright (c) 2005, the Lawrence Journal-World +# Used under the modified BSD license: +# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 +TEMPLATE = <<'HTML' + + + + + <%=h message %> at <%=h req.script_name + req.path_info %> + + + + +
        +

        <%=h message %> (<%= status.to_i %>)

        + + + + + + + + + +
        Request Method:<%=h req.request_method %>
        Request URL:<%=h req.url %>
        +
        +
        +

        <%= detail %>

        +
        + +
        +

        + You're seeing this error because you use Rack::ShowStatus. +

        +
        + + +HTML + + # :startdoc: + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/static.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/static.rb new file mode 100644 index 0000000..f3cac7b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/static.rb @@ -0,0 +1,58 @@ +module Rack + + # The Rack::Static middleware intercepts requests for static files + # (javascript files, images, stylesheets, etc) based on the url prefixes or + # route mappings passed in the options, and serves them using a Rack::File + # object. This allows a Rack stack to serve both static and dynamic content. + # + # Examples: + # + # Serve all requests beginning with /media from the "media" folder located + # in the current directory (ie media/*): + # + # use Rack::Static, :urls => ["/media"] + # + # Serve all requests beginning with /css or /images from the folder "public" + # in the current directory (ie public/css/* and public/images/*): + # + # use Rack::Static, :urls => ["/css", "/images"], :root => "public" + # + # Serve all requests to / with "index.html" from the folder "public" in the + # current directory (ie public/index.html): + # + # use Rack::Static, :urls => {"/" => 'index.html'}, :root => 'public' + # + # Set a fixed Cache-Control header for all served files: + # + # use Rack::Static, :root => 'public', :cache_control => 'public' + # + + class Static + + def initialize(app, options={}) + @app = app + @urls = options[:urls] || ["/favicon.ico"] + root = options[:root] || Dir.pwd + cache_control = options[:cache_control] + @file_server = Rack::File.new(root, cache_control) + end + + def call(env) + path = env["PATH_INFO"] + + unless @urls.kind_of? Hash + can_serve = @urls.any? { |url| path.index(url) == 0 } + else + can_serve = @urls.key? path + end + + if can_serve + env["PATH_INFO"] = @urls[path] if @urls.kind_of? Hash + @file_server.call(env) + else + @app.call(env) + end + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/urlmap.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/urlmap.rb new file mode 100644 index 0000000..4d6b8c6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/urlmap.rb @@ -0,0 +1,60 @@ +module Rack + # Rack::URLMap takes a hash mapping urls or paths to apps, and + # dispatches accordingly. Support for HTTP/1.1 host names exists if + # the URLs start with http:// or https://. + # + # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part + # relevant for dispatch is in the SCRIPT_NAME, and the rest in the + # PATH_INFO. This should be taken care of when you need to + # reconstruct the URL in order to create links. + # + # URLMap dispatches in such a way that the longest paths are tried + # first, since they are most specific. + + class URLMap + NEGATIVE_INFINITY = -1.0 / 0.0 + + def initialize(map = {}) + remap(map) + end + + def remap(map) + longest_path_first = lambda do |(host, location, _, _)| + [host ? -host.size : NEGATIVE_INFINITY, -location.size] + end + @mapping = map.map { |location, app| + if location =~ %r{\Ahttps?://(.*?)(/.*)} + host, location = $1, $2 + else + host = nil + end + + unless location[0] == ?/ + raise ArgumentError, "paths need to start with /" + end + location = location.chomp('/') + match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n') + + [host, location, match, app] + }.sort_by(&longest_path_first) + end + + def call(env) + path = env["PATH_INFO"] + script_name = env['SCRIPT_NAME'] + hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT') + @mapping.each { |host, location, match, app| + next unless (hHost == host || sName == host \ + || (host.nil? && (hHost == sName || hHost == sName+':'+sPort))) + next unless path.to_s =~ match && rest = $1 + next unless rest.empty? || rest[0] == ?/ + env.merge!('SCRIPT_NAME' => (script_name + location), 'PATH_INFO' => rest) + return app.call(env) + } + [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]] + ensure + env.merge! 'PATH_INFO' => path, 'SCRIPT_NAME' => script_name + end + end +end + diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/utils.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/utils.rb new file mode 100644 index 0000000..9bac8eb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/lib/rack/utils.rb @@ -0,0 +1,517 @@ +# -*- encoding: binary -*- +require 'fileutils' +require 'set' +require 'tempfile' +require 'rack/multipart' + +major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i } + +if major == 1 && minor < 9 + require 'rack/backports/uri/common_18' +elsif major == 1 && minor == 9 && patch < 3 + require 'rack/backports/uri/common_192' +else + require 'uri/common' +end + +module Rack + # Rack::Utils contains a grab-bag of useful methods for writing web + # applications adopted from all kinds of Ruby libraries. + + module Utils + # URI escapes. (CGI style space to +) + def escape(s) + URI.encode_www_form_component(s) + end + module_function :escape + + # Like URI escaping, but with %20 instead of +. Strictly speaking this is + # true URI escaping. + def escape_path(s) + escape(s).gsub('+', '%20') + end + module_function :escape_path + + # Unescapes a URI escaped string. + def unescape(s) + URI.decode_www_form_component(s) + end + module_function :unescape + + DEFAULT_SEP = /[&;] */n + + class << self + attr_accessor :key_space_limit + end + + # The default number of bytes to allow parameter keys to take up. + # This helps prevent a rogue client from flooding a Request. + self.key_space_limit = 65536 + + # Stolen from Mongrel, with some small modifications: + # Parses a query string by breaking it up at the '&' + # and ';' characters. You can also use this to parse + # cookies by changing the characters used in the second + # parameter (which defaults to '&;'). + def parse_query(qs, d = nil) + params = {} + + max_key_space = Utils.key_space_limit + bytes = 0 + + (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p| + k, v = p.split('=', 2).map { |x| unescape(x) } + + if k + bytes += k.size + if bytes > max_key_space + raise RangeError, "exceeded available parameter key space" + end + end + + if cur = params[k] + if cur.class == Array + params[k] << v + else + params[k] = [cur, v] + end + else + params[k] = v + end + end + + return params + end + module_function :parse_query + + def parse_nested_query(qs, d = nil) + params = {} + + max_key_space = Utils.key_space_limit + bytes = 0 + + (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p| + k, v = p.split('=', 2).map { |s| unescape(s) } + + if k + bytes += k.size + if bytes > max_key_space + raise RangeError, "exceeded available parameter key space" + end + end + + normalize_params(params, k, v) + end + + return params + end + module_function :parse_nested_query + + def normalize_params(params, name, v = nil) + name =~ %r(\A[\[\]]*([^\[\]]+)\]*) + k = $1 || '' + after = $' || '' + + return if k.empty? + + if after == "" + params[k] = v + elsif after == "[]" + params[k] ||= [] + raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) + params[k] << v + elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) + child_key = $1 + params[k] ||= [] + raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) + if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key) + normalize_params(params[k].last, child_key, v) + else + params[k] << normalize_params({}, child_key, v) + end + else + params[k] ||= {} + raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash) + params[k] = normalize_params(params[k], after, v) + end + + return params + end + module_function :normalize_params + + def build_query(params) + params.map { |k, v| + if v.class == Array + build_query(v.map { |x| [k, x] }) + else + "#{escape(k)}=#{escape(v)}" + end + }.join("&") + end + module_function :build_query + + def build_nested_query(value, prefix = nil) + case value + when Array + value.map { |v| + build_nested_query(v, "#{prefix}[]") + }.join("&") + when Hash + value.map { |k, v| + build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) + }.join("&") + when String + raise ArgumentError, "value must be a Hash" if prefix.nil? + "#{prefix}=#{escape(value)}" + else + prefix + end + end + module_function :build_nested_query + + ESCAPE_HTML = { + "&" => "&", + "<" => "<", + ">" => ">", + "'" => "'", + '"' => """, + "/" => "/" + } + if //.respond_to?(:encoding) + ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys) + else + # On 1.8, there is a kcode = 'u' bug that allows for XSS otherwhise + # TODO doesn't apply to jruby, so a better condition above might be preferable? + ESCAPE_HTML_PATTERN = /#{Regexp.union(*ESCAPE_HTML.keys)}/n + end + + # Escape ampersands, brackets and quotes to their HTML/XML entities. + def escape_html(string) + string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] } + end + module_function :escape_html + + def select_best_encoding(available_encodings, accept_encoding) + # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + + expanded_accept_encoding = + accept_encoding.map { |m, q| + if m == "*" + (available_encodings - accept_encoding.map { |m2, _| m2 }).map { |m2| [m2, q] } + else + [[m, q]] + end + }.inject([]) { |mem, list| + mem + list + } + + encoding_candidates = expanded_accept_encoding.sort_by { |_, q| -q }.map { |m, _| m } + + unless encoding_candidates.include?("identity") + encoding_candidates.push("identity") + end + + expanded_accept_encoding.find_all { |m, q| + q == 0.0 + }.each { |m, _| + encoding_candidates.delete(m) + } + + return (encoding_candidates & available_encodings)[0] + end + module_function :select_best_encoding + + def set_cookie_header!(header, key, value) + case value + when Hash + domain = "; domain=" + value[:domain] if value[:domain] + path = "; path=" + value[:path] if value[:path] + # According to RFC 2109, we need dashes here. + # N.B.: cgi.rb uses spaces... + expires = "; expires=" + + rfc2822(value[:expires].clone.gmtime) if value[:expires] + secure = "; secure" if value[:secure] + httponly = "; HttpOnly" if value[:httponly] + value = value[:value] + end + value = [value] unless Array === value + cookie = escape(key) + "=" + + value.map { |v| escape v }.join("&") + + "#{domain}#{path}#{expires}#{secure}#{httponly}" + + case header["Set-Cookie"] + when nil, '' + header["Set-Cookie"] = cookie + when String + header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n") + when Array + header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n") + end + + nil + end + module_function :set_cookie_header! + + def delete_cookie_header!(header, key, value = {}) + case header["Set-Cookie"] + when nil, '' + cookies = [] + when String + cookies = header["Set-Cookie"].split("\n") + when Array + cookies = header["Set-Cookie"] + end + + cookies.reject! { |cookie| + if value[:domain] + cookie =~ /\A#{escape(key)}=.*domain=#{value[:domain]}/ + else + cookie =~ /\A#{escape(key)}=/ + end + } + + header["Set-Cookie"] = cookies.join("\n") + + set_cookie_header!(header, key, + {:value => '', :path => nil, :domain => nil, + :expires => Time.at(0) }.merge(value)) + + nil + end + module_function :delete_cookie_header! + + # Return the bytesize of String; uses String#size under Ruby 1.8 and + # String#bytesize under 1.9. + if ''.respond_to?(:bytesize) + def bytesize(string) + string.bytesize + end + else + def bytesize(string) + string.size + end + end + module_function :bytesize + + # Modified version of stdlib time.rb Time#rfc2822 to use '%d-%b-%Y' instead + # of '% %b %Y'. + # It assumes that the time is in GMT to comply to the RFC 2109. + # + # NOTE: I'm not sure the RFC says it requires GMT, but is ambigous enough + # that I'm certain someone implemented only that option. + # Do not use %a and %b from Time.strptime, it would use localized names for + # weekday and month. + # + def rfc2822(time) + wday = Time::RFC2822_DAY_NAME[time.wday] + mon = Time::RFC2822_MONTH_NAME[time.mon - 1] + time.strftime("#{wday}, %d-#{mon}-%Y %H:%M:%S GMT") + end + module_function :rfc2822 + + # Parses the "Range:" header, if present, into an array of Range objects. + # Returns nil if the header is missing or syntactically invalid. + # Returns an empty array if none of the ranges are satisfiable. + def byte_ranges(env, size) + # See + http_range = env['HTTP_RANGE'] + return nil unless http_range + ranges = [] + http_range.split(/,\s*/).each do |range_spec| + matches = range_spec.match(/bytes=(\d*)-(\d*)/) + return nil unless matches + r0,r1 = matches[1], matches[2] + if r0.empty? + return nil if r1.empty? + # suffix-byte-range-spec, represents trailing suffix of file + r0 = [size - r1.to_i, 0].max + r1 = size - 1 + else + r0 = r0.to_i + if r1.empty? + r1 = size - 1 + else + r1 = r1.to_i + return nil if r1 < r0 # backwards range is syntactically invalid + r1 = size-1 if r1 >= size + end + end + ranges << (r0..r1) if r0 <= r1 + end + ranges + end + module_function :byte_ranges + + # Context allows the use of a compatible middleware at different points + # in a request handling stack. A compatible middleware must define + # #context which should take the arguments env and app. The first of which + # would be the request environment. The second of which would be the rack + # application that the request would be forwarded to. + class Context + attr_reader :for, :app + + def initialize(app_f, app_r) + raise 'running context does not respond to #context' unless app_f.respond_to? :context + @for, @app = app_f, app_r + end + + def call(env) + @for.context(env, @app) + end + + def recontext(app) + self.class.new(@for, app) + end + + def context(env, app=@app) + recontext(app).call(env) + end + end + + # A case-insensitive Hash that preserves the original case of a + # header when set. + class HeaderHash < Hash + def self.new(hash={}) + HeaderHash === hash ? hash : super(hash) + end + + def initialize(hash={}) + super() + @names = {} + hash.each { |k, v| self[k] = v } + end + + def each + super do |k, v| + yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v) + end + end + + def to_hash + hash = {} + each { |k,v| hash[k] = v } + hash + end + + def [](k) + super(k) || super(@names[k.downcase]) + end + + def []=(k, v) + canonical = k.downcase + delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary + @names[k] = @names[canonical] = k + super k, v + end + + def delete(k) + canonical = k.downcase + result = super @names.delete(canonical) + @names.delete_if { |name,| name.downcase == canonical } + result + end + + def include?(k) + @names.include?(k) || @names.include?(k.downcase) + end + + alias_method :has_key?, :include? + alias_method :member?, :include? + alias_method :key?, :include? + + def merge!(other) + other.each { |k, v| self[k] = v } + self + end + + def merge(other) + hash = dup + hash.merge! other + end + + def replace(other) + clear + other.each { |k, v| self[k] = v } + self + end + end + + # Every standard HTTP code mapped to the appropriate message. + # Generated with: + # curl -s http://www.iana.org/assignments/http-status-codes | \ + # ruby -ane 'm = /^(\d{3}) +(\S[^\[(]+)/.match($_) and + # puts " #{m[1]} => \x27#{m[2].strip}x27,"' + HTTP_STATUS_CODES = { + 100 => 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-Status', + 226 => 'IM Used', + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => 'Reserved', + 307 => 'Temporary Redirect', + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 422 => 'Unprocessable Entity', + 423 => 'Locked', + 424 => 'Failed Dependency', + 426 => 'Upgrade Required', + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 506 => 'Variant Also Negotiates', + 507 => 'Insufficient Storage', + 510 => 'Not Extended', + } + + # Responses with HTTP status codes that should not have an entity body + STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 304) + + SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message| + [message.downcase.gsub(/\s|-/, '_').to_sym, code] + }.flatten] + + def status_code(status) + if status.is_a?(Symbol) + SYMBOL_TO_STATUS_CODE[status] || 500 + else + status.to_i + end + end + module_function :status_code + + Multipart = Rack::Multipart + + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/rack.gemspec b/vendor/ruby/1.9.1/gems/rack-1.3.6/rack.gemspec new file mode 100644 index 0000000..645d101 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/rack.gemspec @@ -0,0 +1,37 @@ +Gem::Specification.new do |s| + s.name = "rack" + s.version = "1.3.6" + s.platform = Gem::Platform::RUBY + s.summary = "a modular Ruby webserver interface" + + s.description = <<-EOF +Rack provides minimal, modular and adaptable interface for developing +web applications in Ruby. By wrapping HTTP requests and responses in +the simplest way possible, it unifies and distills the API for web +servers, web frameworks, and software in between (the so-called +middleware) into a single method call. + +Also see http://rack.rubyforge.org. +EOF + + s.files = Dir['{bin/*,contrib/*,example/*,lib/**/*,test/**/*}'] + + %w(COPYING KNOWN-ISSUES rack.gemspec Rakefile README.rdoc SPEC) + s.bindir = 'bin' + s.executables << 'rackup' + s.require_path = 'lib' + s.extra_rdoc_files = ['README.rdoc', 'KNOWN-ISSUES'] + s.test_files = Dir['test/spec_*.rb'] + + s.author = 'Christian Neukirchen' + s.email = 'chneukirchen@gmail.com' + s.homepage = 'http://rack.rubyforge.org' + s.rubyforge_project = 'rack' + + s.add_development_dependency 'bacon' + s.add_development_dependency 'rake' + + s.add_development_dependency 'fcgi' + s.add_development_dependency 'memcache-client' + s.add_development_dependency 'mongrel', '>= 1.2.0.pre2' + s.add_development_dependency 'thin' +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/anything.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/anything.rb new file mode 100644 index 0000000..c07f82c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/anything.rb @@ -0,0 +1,5 @@ +class Anything + def self.call(env) + [200, {'Content-Type' => 'text/plain'}, ['OK']] + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/comment.ru b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/comment.ru new file mode 100644 index 0000000..0722f0a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/comment.ru @@ -0,0 +1,4 @@ +=begin + +=end +run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/end.ru b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/end.ru new file mode 100644 index 0000000..8eea56e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/end.ru @@ -0,0 +1,3 @@ +run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } +__END__ +Should not be evaluated diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/options.ru b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/options.ru new file mode 100644 index 0000000..8562da6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/builder/options.ru @@ -0,0 +1,2 @@ +#\ -d +run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/lighttpd.conf b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/lighttpd.conf new file mode 100755 index 0000000..721b76a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/lighttpd.conf @@ -0,0 +1,25 @@ +server.modules = ("mod_fastcgi", "mod_cgi") +server.document-root = "." +server.errorlog = var.CWD + "/lighttpd.errors" +server.port = 9203 + +server.event-handler = "select" + +cgi.assign = ("/test" => "", +# ".ru" => "" + ) + +fastcgi.server = ( + "test.fcgi" => ("localhost" => + ("min-procs" => 1, + "socket" => "/tmp/rack-test-fcgi", + "bin-path" => "test.fcgi")), + "test.ru" => ("localhost" => + ("min-procs" => 1, + "socket" => "/tmp/rack-test-ru-fcgi", + "bin-path" => CWD + "/rackup_stub.rb test.ru")), + "sample_rackup.ru" => ("localhost" => + ("min-procs" => 1, + "socket" => "/tmp/rack-test-rackup-fcgi", + "bin-path" => CWD + "/rackup_stub.rb sample_rackup.ru")), + ) diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/rackup_stub.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/rackup_stub.rb new file mode 100755 index 0000000..a216cdc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/rackup_stub.rb @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# -*- ruby -*- + +$:.unshift '../../lib' +require 'rack' +Rack::Server.start diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/sample_rackup.ru b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/sample_rackup.ru new file mode 100755 index 0000000..86d99e6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/sample_rackup.ru @@ -0,0 +1,5 @@ +# -*- ruby -*- + +require '../testrequest' + +run TestRequest.new diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test new file mode 100755 index 0000000..e4837a4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +# -*- ruby -*- + +$: << File.join(File.dirname(__FILE__), "..", "..", "lib") + +require 'rack' +require '../testrequest' + +Rack::Handler::CGI.run(Rack::Lint.new(TestRequest.new)) diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test.fcgi b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test.fcgi new file mode 100755 index 0000000..5e104fc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test.fcgi @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +# -*- ruby -*- + +$:.unshift '../../lib' +require 'rack' +require '../testrequest' + +Rack::Handler::FastCGI.run(Rack::Lint.new(TestRequest.new)) diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test.ru b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test.ru new file mode 100755 index 0000000..bd3ee72 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/cgi/test.ru @@ -0,0 +1,5 @@ +#!../../bin/rackup +# -*- ruby -*- + +require '../testrequest' +run TestRequest.new diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/gemloader.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/gemloader.rb new file mode 100644 index 0000000..382e8b8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/gemloader.rb @@ -0,0 +1,6 @@ +require 'rubygems' +project = 'rack' +gemspec = File.expand_path("#{project}.gemspec", Dir.pwd) +Gem::Specification.load(gemspec).dependencies.each do |dep| + gem dep.name, *dep.requirement.as_list +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/bad_robots b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/bad_robots new file mode 100644 index 0000000..7e5bd41 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/bad_robots @@ -0,0 +1,259 @@ +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="bbbbbbbbbbbbbbb" + +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaa + +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="ccccccc" + +ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="file.name" + +INPUTMSG.gz +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="file.content_type" + +application/octet-stream +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="file.path" + +/var/tmp/uploads/4/0001728414 +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="file.md5" + +aa73198feb4b4c1c3186f5e7466cbbcc +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="file.size" + +13212 +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="size" + +80892 +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="mail_server_id" + +<1111111111.22222222.3333333333333.JavaMail.app@ffff-aaaa.dddd> + +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="addresses" + +{"campsy_programmer@pinkedum.com":{"domain":"pinkedum.com","name":"Campsy Programmer","type":["env_sender"],"mailbox":"campsy_programmer"},"tex@rapidcity.com":{"domain":"rapidcity.com","name":"Big Tex","type":["env_recipients","to"],"mailbox":"tex"},"group-digests@linkedin.com":{"domain":"linkedin.com","name":"Group Members","type":["from"],"mailbox":"group-digests"}} +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="received_on" + +2009-11-15T14:21:11Z +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="id" + +dbfd9804d26d11deab24e3037639bf77 +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon +Content-Disposition: form-data; name="ip_address" + +127.0.0.1 +--1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/binary b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/binary new file mode 100644 index 0000000..a3bd67c Binary files /dev/null and b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/binary differ diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/content_type_and_no_filename b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/content_type_and_no_filename new file mode 100644 index 0000000..bd4c89b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/content_type_and_no_filename @@ -0,0 +1,6 @@ +--AaB03x +Content-Disposition: form-data; name="text" +Content-Type: text/plain; charset=US-ASCII + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/empty b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/empty new file mode 100644 index 0000000..f0f7983 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/empty @@ -0,0 +1,10 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files"; filename="file1.txt" +Content-Type: text/plain + + +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/fail_16384_nofile b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/fail_16384_nofile new file mode 100644 index 0000000..bdcd332 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/fail_16384_nofile @@ -0,0 +1,814 @@ +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="_method" + +put +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="authenticity_token" + +XCUgSyYsZ+iHQunq/yCSKFzjeVmsXV/WcphHQ0J+05I= +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[SESE]" + +BooBar +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[BBBBBBBBB]" + +18 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[CCCCCCCCCCCCCCCCCCC]" + +0 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[STARTFOO]" + +2009-11-04 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[ENDFOO]" + +2009-12-01 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[DDDDDDDD]" + +0 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[DDDDDDDD]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[EEEEEEEEEE]" + +10000 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[FFFFFFFFF]" + +boskoizcool +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[GGGGGGGGGGG]" + +0 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[GGGGGGGGGGG]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[YYYYYYYYYYYYYYY]" + +5.00 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[ZZZZZZZZZZZZZ]" + +mille +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[XXXXXXXXXXXXXXXXXXXXX]" + +0 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][1][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][2][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][3][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][4][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][5][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][6][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][9]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][10]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][11]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][12]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][13]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][14]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][15]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][16]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][17]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][18]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][19]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][20]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][21]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][22]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][23]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][0]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][1]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][2]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][3]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][4]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][5]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][6]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][7]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[VVVVVVVVVVVVVVVVVVVVVVV][0][8]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][ZEZE]" + +PLAPLAPLAINCINCINC +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][123412341234e]" + +SITE +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[WWWWWWWWWWWWWWWWWWWWWWWWW][678][12345678901]" + +56 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_type]" + +none +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][has_hashashas_has]" + +0 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][frefrefre_fre_freee]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][frefrefre_fre_frefre]" + +forever +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][self_block]" + +0 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][COUCOUN]" + + +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][REGREG]" + + +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_wizard][GGG_RULES][][c1c1]" + + +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA_TARTARTAR_wizard_rule" + + +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[TARTARTAR_rule]" + + +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[selection_selection]" + +R +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-1][selection_selection]" + +1 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-1][ba_unit_id]" + +1015 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-2][selection_selection]" + +2 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[PLAPLAPLA_MEMMEMMEMM_ATTRATTRER][new][-2][ba_unit_id]" + +1017 +------WebKitFormBoundaryWsY0GnpbI5U7ztzo +Content-Disposition: form-data; name="AAAAAAAAAAAAAAAAAAA[tile_name]" + + +------WebKitFormBoundaryWsY0GnpbI5U7ztzo-- + diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/file1.txt b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/file1.txt new file mode 100644 index 0000000..0839b2e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/file1.txt @@ -0,0 +1 @@ +contents \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_and_modification_param b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_and_modification_param new file mode 100644 index 0000000..20893f4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_and_modification_param @@ -0,0 +1,7 @@ +--AaB03x +Content-Type: image/jpeg +Content-Disposition: attachment; name="files"; filename=genome.jpeg; modification-date="Wed, 12 Feb 1997 16:29:51 -0500"; +Content-Description: a complete map of the human genome + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_escaped_quotes b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_escaped_quotes new file mode 100644 index 0000000..0a332df --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_escaped_quotes @@ -0,0 +1,6 @@ +--AaB03x +Content-Disposition: form-data; name="files"; filename="escape \"quotes" +Content-Type: application/octet-stream + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_escaped_quotes_and_modification_param b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_escaped_quotes_and_modification_param new file mode 100644 index 0000000..7619bd5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_escaped_quotes_and_modification_param @@ -0,0 +1,7 @@ +--AaB03x +Content-Type: image/jpeg +Content-Disposition: attachment; name="files"; filename=""human" genome.jpeg"; modification-date="Wed, 12 Feb 1997 16:29:51 -0500"; +Content-Description: a complete map of the human genome + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_percent_escaped_quotes b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_percent_escaped_quotes new file mode 100644 index 0000000..7db0641 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_percent_escaped_quotes @@ -0,0 +1,6 @@ +--AaB03x +Content-Disposition: form-data; name="files"; filename="escape %22quotes" +Content-Type: application/octet-stream + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_unescaped_quotes b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_unescaped_quotes new file mode 100644 index 0000000..9a291e8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/filename_with_unescaped_quotes @@ -0,0 +1,6 @@ +--AaB03x +Content-Disposition: form-data; name="files"; filename="escape "quotes" +Content-Type: application/octet-stream + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/ie b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/ie new file mode 100644 index 0000000..eae06ab --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/ie @@ -0,0 +1,6 @@ +--AaB03x +Content-Disposition: form-data; name="files"; filename="C:\Documents and Settings\Administrator\Desktop\file1.txt" +Content-Type: text/plain + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/mixed_files b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/mixed_files new file mode 100644 index 0000000..624d804 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/mixed_files @@ -0,0 +1,21 @@ +--AaB03x +Content-Disposition: form-data; name="foo" + +bar +--AaB03x +Content-Disposition: form-data; name="files" +Content-Type: multipart/mixed, boundary=BbC04y + +--BbC04y +Content-Disposition: attachment; filename="file.txt" +Content-Type: text/plain + +contents +--BbC04y +Content-Disposition: attachment; filename="flowers.jpg" +Content-Type: image/jpeg +Content-Transfer-Encoding: binary + +contents +--BbC04y-- +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/nested b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/nested new file mode 100644 index 0000000..5197882 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/nested @@ -0,0 +1,10 @@ +--AaB03x +Content-Disposition: form-data; name="foo[submit-name]" + +Larry +--AaB03x +Content-Disposition: form-data; name="foo[files]"; filename="file1.txt" +Content-Type: text/plain + +contents +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/none b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/none new file mode 100644 index 0000000..d66f473 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/none @@ -0,0 +1,9 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files"; filename="" + + +--AaB03x-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/semicolon b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/semicolon new file mode 100644 index 0000000..00fd68a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/semicolon @@ -0,0 +1,6 @@ +--AaB03x +Content-Disposition: form-data; name="files"; filename="fi;le1.txt" +Content-Type: text/plain + +contents +--AaB03x-- \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/text b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/text new file mode 100644 index 0000000..01376d0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/text @@ -0,0 +1,15 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="submit-name-with-content" +Content-Type: text/plain + +Berry +--AaB03x +Content-Disposition: form-data; name="files"; filename="file1.txt" +Content-Type: text/plain + +contents +--AaB03x-- \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/webkit b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/webkit new file mode 100644 index 0000000..1375af3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/multipart/webkit @@ -0,0 +1,32 @@ +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="_method" + +put +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="profile[blog]" + + +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="profile[public_email]" + + +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="profile[interests]" + + +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="profile[bio]" + +hello + +"quote" +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="media"; filename="" +Content-Type: application/octet-stream + + +------WebKitFormBoundaryWLHCs9qmcJJoyjKR +Content-Disposition: form-data; name="commit" + +Save +------WebKitFormBoundaryWLHCs9qmcJJoyjKR-- diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/rackup/config.ru b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/rackup/config.ru new file mode 100644 index 0000000..f1e2e1f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/rackup/config.ru @@ -0,0 +1,31 @@ +require "#{File.dirname(__FILE__)}/../testrequest" + +$stderr = File.open("#{File.dirname(__FILE__)}/log_output", "w") + +class EnvMiddleware + def initialize(app) + @app = app + end + + def call(env) + # provides a way to test that lint is present + if env["PATH_INFO"] == "/broken_lint" + return [200, {}, ["Broken Lint"]] + # provides a way to kill the process without knowing the pid + elsif env["PATH_INFO"] == "/die" + exit! + end + + env["test.$DEBUG"] = $DEBUG + env["test.$EVAL"] = BUKKIT if defined?(BUKKIT) + env["test.$VERBOSE"] = $VERBOSE + env["test.$LOAD_PATH"] = $LOAD_PATH + env["test.stderr"] = File.expand_path($stderr.path) + env["test.Ping"] = defined?(Ping) + env["test.pid"] = Process.pid + @app.call(env) + end +end + +use EnvMiddleware +run TestRequest.new diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/registering_handler/rack/handler/registering_myself.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/registering_handler/rack/handler/registering_myself.rb new file mode 100644 index 0000000..1635efa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/registering_handler/rack/handler/registering_myself.rb @@ -0,0 +1,8 @@ +module Rack + module Handler + class RegisteringMyself + end + + register :registering_myself, RegisteringMyself + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_auth_basic.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_auth_basic.rb new file mode 100644 index 0000000..5ef2643 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_auth_basic.rb @@ -0,0 +1,70 @@ +require 'rack/auth/basic' +require 'rack/mock' + +describe Rack::Auth::Basic do + def realm + 'WallysWorld' + end + + def unprotected_app + lambda { |env| [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ] } + end + + def protected_app + app = Rack::Auth::Basic.new(unprotected_app) { |username, password| 'Boss' == username } + app.realm = realm + app + end + + before do + @request = Rack::MockRequest.new(protected_app) + end + + def request_with_basic_auth(username, password, &block) + request 'HTTP_AUTHORIZATION' => 'Basic ' + ["#{username}:#{password}"].pack("m*"), &block + end + + def request(headers = {}) + yield @request.get('/', headers) + end + + def assert_basic_auth_challenge(response) + response.should.be.a.client_error + response.status.should.equal 401 + response.should.include 'WWW-Authenticate' + response.headers['WWW-Authenticate'].should =~ /Basic realm="#{Regexp.escape(realm)}"/ + response.body.should.be.empty + end + + should 'challenge correctly when no credentials are specified' do + request do |response| + assert_basic_auth_challenge response + end + end + + should 'rechallenge if incorrect credentials are specified' do + request_with_basic_auth 'joe', 'password' do |response| + assert_basic_auth_challenge response + end + end + + should 'return application output if correct credentials are specified' do + request_with_basic_auth 'Boss', 'password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Boss' + end + end + + should 'return 400 Bad Request if different auth scheme used' do + request 'HTTP_AUTHORIZATION' => 'Digest params' do |response| + response.should.be.a.client_error + response.status.should.equal 400 + response.should.not.include 'WWW-Authenticate' + end + end + + it 'takes realm as optional constructor arg' do + app = Rack::Auth::Basic.new(unprotected_app, realm) { true } + realm.should == app.realm + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_auth_digest.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_auth_digest.rb new file mode 100644 index 0000000..c85d717 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_auth_digest.rb @@ -0,0 +1,244 @@ +require 'rack/auth/digest/md5' +require 'rack/mock' + +describe Rack::Auth::Digest::MD5 do + def realm + 'WallysWorld' + end + + def unprotected_app + lambda do |env| + friend = Rack::Utils.parse_query(env["QUERY_STRING"])["friend"] + [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}#{friend ? " and #{friend}" : ''}"] ] + end + end + + def protected_app + Rack::Auth::Digest::MD5.new(unprotected_app, :realm => realm, :opaque => 'this-should-be-secret') do |username| + { 'Alice' => 'correct-password' }[username] + end + end + + def protected_app_with_hashed_passwords + app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username| + username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil + end + app.realm = realm + app.opaque = 'this-should-be-secret' + app.passwords_hashed = true + app + end + + def partially_protected_app + Rack::URLMap.new({ + '/' => unprotected_app, + '/protected' => protected_app + }) + end + + def protected_app_with_method_override + Rack::MethodOverride.new(protected_app) + end + + before do + @request = Rack::MockRequest.new(protected_app) + end + + def request(method, path, headers = {}, &block) + response = @request.request(method, path, headers) + block.call(response) if block + return response + end + + class MockDigestRequest + def initialize(params) + @params = params + end + def method_missing(sym) + if @params.has_key? k = sym.to_s + return @params[k] + end + super + end + def method + @params['method'] + end + def response(password) + Rack::Auth::Digest::MD5.new(nil).send :digest, self, password + end + end + + def request_with_digest_auth(method, path, username, password, options = {}, &block) + request_options = {} + request_options[:input] = options.delete(:input) if options.include? :input + + response = request(method, path, request_options) + + return response unless response.status == 401 + + if wait = options.delete(:wait) + sleep wait + end + + challenge = response['WWW-Authenticate'].split(' ', 2).last + + params = Rack::Auth::Digest::Params.parse(challenge) + + params['username'] = username + params['nc'] = '00000001' + params['cnonce'] = 'nonsensenonce' + params['uri'] = path + + params['method'] = method + + params.update options + + params['response'] = MockDigestRequest.new(params).response(password) + + request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block) + end + + def assert_digest_auth_challenge(response) + response.should.be.a.client_error + response.status.should.equal 401 + response.should.include 'WWW-Authenticate' + response.headers['WWW-Authenticate'].should =~ /^Digest / + response.body.should.be.empty + end + + def assert_bad_request(response) + response.should.be.a.client_error + response.status.should.equal 400 + response.should.not.include 'WWW-Authenticate' + end + + should 'challenge when no credentials are specified' do + request 'GET', '/' do |response| + assert_digest_auth_challenge response + end + end + + should 'return application output if correct credentials given' do + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + should 'return application output if correct credentials given (hashed passwords)' do + @request = Rack::MockRequest.new(protected_app_with_hashed_passwords) + + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + should 'rechallenge if incorrect username given' do + request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response| + assert_digest_auth_challenge response + end + end + + should 'rechallenge if incorrect password given' do + request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response| + assert_digest_auth_challenge response + end + end + + should 'rechallenge if incorrect user and blank password given' do + request_with_digest_auth 'GET', '/', 'Bob', '' do |response| + assert_digest_auth_challenge response + end + end + + should 'rechallenge with stale parameter if nonce is stale' do + begin + Rack::Auth::Digest::Nonce.time_limit = 1 + + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response| + assert_digest_auth_challenge response + response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/ + end + ensure + Rack::Auth::Digest::Nonce.time_limit = nil + end + end + + should 'return 400 Bad Request if incorrect qop given' do + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response| + assert_bad_request response + end + end + + should 'return 400 Bad Request if incorrect uri given' do + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response| + assert_bad_request response + end + end + + should 'return 400 Bad Request if different auth scheme used' do + request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response| + assert_bad_request response + end + end + + should 'not require credentials for unprotected path' do + @request = Rack::MockRequest.new(partially_protected_app) + request 'GET', '/' do |response| + response.should.be.ok + end + end + + should 'challenge when no credentials are specified for protected path' do + @request = Rack::MockRequest.new(partially_protected_app) + request 'GET', '/protected' do |response| + assert_digest_auth_challenge response + end + end + + should 'return application output if correct credentials given for protected path' do + @request = Rack::MockRequest.new(partially_protected_app) + request_with_digest_auth 'GET', '/protected', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + should 'return application output when used with a query string and path as uri' do + @request = Rack::MockRequest.new(partially_protected_app) + request_with_digest_auth 'GET', '/protected?friend=Mike', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice and Mike' + end + end + + should 'return application output when used with a query string and fullpath as uri' do + @request = Rack::MockRequest.new(partially_protected_app) + qs_uri = '/protected?friend=Mike' + request_with_digest_auth 'GET', qs_uri, 'Alice', 'correct-password', 'uri' => qs_uri do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice and Mike' + end + end + + should 'return application output if correct credentials given for POST' do + request_with_digest_auth 'POST', '/', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + should 'return application output if correct credentials given for PUT (using method override of POST)' do + @request = Rack::MockRequest.new(protected_app_with_method_override) + request_with_digest_auth 'POST', '/', 'Alice', 'correct-password', :input => "_method=put" do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + it 'takes realm as optional constructor arg' do + app = Rack::Auth::Digest::MD5.new(unprotected_app, realm) { true } + realm.should == app.realm + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_body_proxy.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_body_proxy.rb new file mode 100644 index 0000000..64bd65f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_body_proxy.rb @@ -0,0 +1,48 @@ +require 'rack/body_proxy' + +describe Rack::BodyProxy do + should 'call each on the wrapped body' do + called = false + proxy = Rack::BodyProxy.new(['foo']) { } + proxy.each do |str| + called = true + str.should.equal 'foo' + end + called.should.equal true + end + + should 'call close on the wrapped body' do + body = StringIO.new + proxy = Rack::BodyProxy.new(body) { } + proxy.close + body.should.be.closed + end + + should 'only call close on the wrapped body if it responds to close' do + body = [] + proxy = Rack::BodyProxy.new(body) { } + proc { proxy.close }.should.not.raise + end + + should 'call the passed block on close' do + called = false + proxy = Rack::BodyProxy.new([]) { called = true } + called.should.equal false + proxy.close + called.should.equal true + end + + should 'not close more than one time' do + count = 0 + proxy = Rack::BodyProxy.new([]) { count += 1; raise "Block invoked more than 1 time!" if count > 1 } + 2.times { proxy.close } + count.should.equal 1 + end + + should 'be closed when the callback is triggered' do + closed = false + proxy = Rack::BodyProxy.new([]) { closed = proxy.closed? } + proxy.close + closed.should.equal true + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_builder.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_builder.rb new file mode 100644 index 0000000..f7501ae --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_builder.rb @@ -0,0 +1,152 @@ +require 'rack/builder' +require 'rack/mock' +require 'rack/showexceptions' +require 'rack/urlmap' + +class NothingMiddleware + def initialize(app) + @app = app + end + def call(env) + @@env = env + response = @app.call(env) + response + end + def self.env + @@env + end +end + +describe Rack::Builder do + it "supports mapping" do + app = Rack::Builder.new do + map '/' do |outer_env| + run lambda { |inner_env| [200, {}, ['root']] } + end + map '/sub' do + run lambda { |inner_env| [200, {}, ['sub']] } + end + end.to_app + Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root' + Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub' + end + + it "doesn't dupe env even when mapping" do + app = Rack::Builder.new do + use NothingMiddleware + map '/' do |outer_env| + run lambda { |inner_env| + inner_env['new_key'] = 'new_value' + [200, {}, ['root']] + } + end + end.to_app + Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root' + NothingMiddleware.env['new_key'].should.equal 'new_value' + end + + it "chains apps by default" do + app = Rack::Builder.new do + use Rack::ShowExceptions + run lambda { |env| raise "bzzzt" } + end.to_app + + Rack::MockRequest.new(app).get("/").should.be.server_error + Rack::MockRequest.new(app).get("/").should.be.server_error + Rack::MockRequest.new(app).get("/").should.be.server_error + end + + it "has implicit #to_app" do + app = Rack::Builder.new do + use Rack::ShowExceptions + run lambda { |env| raise "bzzzt" } + end + + Rack::MockRequest.new(app).get("/").should.be.server_error + Rack::MockRequest.new(app).get("/").should.be.server_error + Rack::MockRequest.new(app).get("/").should.be.server_error + end + + it "supports blocks on use" do + app = Rack::Builder.new do + use Rack::ShowExceptions + use Rack::Auth::Basic do |username, password| + 'secret' == password + end + + run lambda { |env| [200, {}, ['Hi Boss']] } + end + + response = Rack::MockRequest.new(app).get("/") + response.should.be.client_error + response.status.should.equal 401 + + # with auth... + response = Rack::MockRequest.new(app).get("/", + 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*")) + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Boss' + end + + it "has explicit #to_app" do + app = Rack::Builder.app do + use Rack::ShowExceptions + run lambda { |env| raise "bzzzt" } + end + + Rack::MockRequest.new(app).get("/").should.be.server_error + Rack::MockRequest.new(app).get("/").should.be.server_error + Rack::MockRequest.new(app).get("/").should.be.server_error + end + + should "initialize apps once" do + app = Rack::Builder.new do + class AppClass + def initialize + @called = 0 + end + def call(env) + raise "bzzzt" if @called > 0 + @called += 1 + [200, {'Content-Type' => 'text/plain'}, ['OK']] + end + end + + use Rack::ShowExceptions + run AppClass.new + end + + Rack::MockRequest.new(app).get("/").status.should.equal 200 + Rack::MockRequest.new(app).get("/").should.be.server_error + end + + describe "parse_file" do + def config_file(name) + File.join(File.dirname(__FILE__), 'builder', name) + end + + it "parses commented options" do + app, options = Rack::Builder.parse_file config_file('options.ru') + options[:debug].should.be.true + Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' + end + + it "removes __END__ before evaluating app" do + app, options = Rack::Builder.parse_file config_file('end.ru') + Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' + end + + it "supports multi-line comments" do + lambda { + Rack::Builder.parse_file config_file('comment.ru') + }.should.not.raise(SyntaxError) + end + + it "requires anything not ending in .ru" do + $: << File.dirname(__FILE__) + app, options = Rack::Builder.parse_file 'builder/anything' + Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK' + $:.pop + end + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_cascade.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_cascade.rb new file mode 100644 index 0000000..c2c4920 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_cascade.rb @@ -0,0 +1,45 @@ +require 'rack/cascade' +require 'rack/file' +require 'rack/urlmap' +require 'rack/mock' + +describe Rack::Cascade do + docroot = File.expand_path(File.dirname(__FILE__)) + app1 = Rack::File.new(docroot) + + app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" }) + + app3 = Rack::URLMap.new("/foo" => lambda { |env| + [200, { "Content-Type" => "text/plain"}, [""]]}) + + should "dispatch onward on 404 by default" do + cascade = Rack::Cascade.new([app1, app2, app3]) + Rack::MockRequest.new(cascade).get("/cgi/test").should.be.ok + Rack::MockRequest.new(cascade).get("/foo").should.be.ok + Rack::MockRequest.new(cascade).get("/toobad").should.be.not_found + Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.forbidden + end + + should "dispatch onward on whatever is passed" do + cascade = Rack::Cascade.new([app1, app2, app3], [404, 403]) + Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found + end + + should "return 404 if empty" do + Rack::MockRequest.new(Rack::Cascade.new([])).get('/').should.be.not_found + end + + should "append new app" do + cascade = Rack::Cascade.new([], [404, 403]) + Rack::MockRequest.new(cascade).get('/').should.be.not_found + cascade << app2 + Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found + Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found + cascade << app1 + Rack::MockRequest.new(cascade).get('/cgi/test').should.be.ok + Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.forbidden + Rack::MockRequest.new(cascade).get('/foo').should.be.not_found + cascade << app3 + Rack::MockRequest.new(cascade).get('/foo').should.be.ok + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_cgi.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_cgi.rb new file mode 100644 index 0000000..345a49a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_cgi.rb @@ -0,0 +1,102 @@ +begin +require File.expand_path('../testrequest', __FILE__) +require 'rack/handler/cgi' + +describe Rack::Handler::CGI do + extend TestRequest::Helpers + + @host = '0.0.0.0' + @port = 9203 + + if `which lighttpd` && !$?.success? + raise "lighttpd not found" + end + + # Keep this first. + $pid = fork { + ENV['RACK_ENV'] = 'deployment' + ENV['RUBYLIB'] = [ + File.expand_path('../../lib', __FILE__), + ENV['RUBYLIB'], + ].compact.join(':') + + Dir.chdir(File.expand_path("../cgi", __FILE__)) do + exec "lighttpd -D -f lighttpd.conf" + end + } + + should "respond" do + sleep 1 + GET("/test") + response.should.not.be.nil + end + + should "be a lighttpd" do + GET("/test") + status.should.equal 200 + response["SERVER_SOFTWARE"].should =~ /lighttpd/ + response["HTTP_VERSION"].should.equal "HTTP/1.1" + response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" + response["SERVER_PORT"].should.equal @port.to_s + response["SERVER_NAME"].should.equal @host + end + + should "have rack headers" do + GET("/test") + response["rack.version"].should.equal([1,1]) + response["rack.multithread"].should.be.false + response["rack.multiprocess"].should.be.true + response["rack.run_once"].should.be.true + end + + should "have CGI headers on GET" do + GET("/test") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/" + response["PATH_INFO"].should.be.nil + response["QUERY_STRING"].should.equal "" + response["test.postdata"].should.equal "" + + GET("/test/foo?quux=1") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/" + response["PATH_INFO"].should.equal "/foo" + response["QUERY_STRING"].should.equal "quux=1" + end + + should "have CGI headers on POST" do + POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) + status.should.equal 200 + response["REQUEST_METHOD"].should.equal "POST" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/" + response["QUERY_STRING"].should.equal "" + response["HTTP_X_TEST_HEADER"].should.equal "42" + response["test.postdata"].should.equal "rack-form-data=23" + end + + should "support HTTP auth" do + GET("/test", {:user => "ruth", :passwd => "secret"}) + response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" + end + + should "set status" do + GET("/test?secret") + status.should.equal 403 + response["rack.url_scheme"].should.equal "http" + end + + # Keep this last. + should "shutdown" do + Process.kill 15, $pid + Process.wait($pid).should == $pid + end +end + +rescue RuntimeError + $stderr.puts "Skipping Rack::Handler::CGI tests (lighttpd is required). Install lighttpd and try again." +rescue NotImplementedError + $stderr.puts "Your Ruby implemenation or platform does not support fork. Skipping Rack::Handler::CGI tests." +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_chunked.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_chunked.rb new file mode 100644 index 0000000..04c22fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_chunked.rb @@ -0,0 +1,60 @@ +require 'rack/chunked' +require 'rack/mock' + +describe Rack::Chunked do + before do + @env = Rack::MockRequest. + env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET') + end + + should 'chunk responses with no Content-Length' do + app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] } + response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env)) + response.headers.should.not.include 'Content-Length' + response.headers['Transfer-Encoding'].should.equal 'chunked' + response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n" + end + + should 'chunks empty bodies properly' do + app = lambda { |env| [200, {}, []] } + response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env)) + response.headers.should.not.include 'Content-Length' + response.headers['Transfer-Encoding'].should.equal 'chunked' + response.body.should.equal "0\r\n\r\n" + end + + should 'not modify response when Content-Length header present' do + app = lambda { |env| [200, {'Content-Length'=>'12'}, ['Hello', ' ', 'World!']] } + status, headers, body = Rack::Chunked.new(app).call(@env) + status.should.equal 200 + headers.should.not.include 'Transfer-Encoding' + headers.should.include 'Content-Length' + body.join.should.equal 'Hello World!' + end + + should 'not modify response when client is HTTP/1.0' do + app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] } + @env['HTTP_VERSION'] = 'HTTP/1.0' + status, headers, body = Rack::Chunked.new(app).call(@env) + status.should.equal 200 + headers.should.not.include 'Transfer-Encoding' + body.join.should.equal 'Hello World!' + end + + should 'not modify response when Transfer-Encoding header already present' do + app = lambda { |env| [200, {'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']] } + status, headers, body = Rack::Chunked.new(app).call(@env) + status.should.equal 200 + headers['Transfer-Encoding'].should.equal 'identity' + body.join.should.equal 'Hello World!' + end + + [100, 204, 304].each do |status_code| + should "not modify response when status code is #{status_code}" do + app = lambda { |env| [status_code, {}, []] } + status, headers, _ = Rack::Chunked.new(app).call(@env) + status.should.equal status_code + headers.should.not.include 'Transfer-Encoding' + end + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_commonlogger.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_commonlogger.rb new file mode 100644 index 0000000..9172750 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_commonlogger.rb @@ -0,0 +1,56 @@ +require 'rack/commonlogger' +require 'rack/mock' + +describe Rack::CommonLogger do + obj = 'foobar' + length = obj.size + + app = lambda { |env| + [200, + {"Content-Type" => "text/html", "Content-Length" => length.to_s}, + [obj]]} + app_without_length = lambda { |env| + [200, + {"Content-Type" => "text/html"}, + []]} + app_with_zero_length = lambda { |env| + [200, + {"Content-Type" => "text/html", "Content-Length" => "0"}, + []]} + + should "log to rack.errors by default" do + res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/") + + res.errors.should.not.be.empty + res.errors.should =~ /"GET \/ " 200 #{length} / + end + + should "log to anything with +write+" do + log = StringIO.new + Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/") + + log.string.should =~ /"GET \/ " 200 #{length} / + end + + should "log - content length if header is missing" do + res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/") + + res.errors.should.not.be.empty + res.errors.should =~ /"GET \/ " 200 - / + end + + should "log - content length if header is zero" do + res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/") + + res.errors.should.not.be.empty + res.errors.should =~ /"GET \/ " 200 - / + end + + def length + 123 + end + + def self.obj + "hello world" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_conditionalget.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_conditionalget.rb new file mode 100644 index 0000000..a21da45 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_conditionalget.rb @@ -0,0 +1,98 @@ +require 'time' +require 'rack/conditionalget' +require 'rack/mock' + +describe Rack::ConditionalGet do + should "set a 304 status and truncate body when If-Modified-Since hits" do + timestamp = Time.now.httpdate + app = Rack::ConditionalGet.new(lambda { |env| + [200, {'Last-Modified'=>timestamp}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp) + + response.status.should.equal 304 + response.body.should.be.empty + end + + should "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do + app = Rack::ConditionalGet.new(lambda { |env| + [200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate) + + response.status.should.equal 304 + response.body.should.be.empty + end + + should "set a 304 status and truncate body when If-None-Match hits" do + app = Rack::ConditionalGet.new(lambda { |env| + [200, {'Etag'=>'1234'}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_NONE_MATCH' => '1234') + + response.status.should.equal 304 + response.body.should.be.empty + end + + should "not set a 304 status if If-Modified-Since hits but Etag does not" do + timestamp = Time.now.httpdate + app = Rack::ConditionalGet.new(lambda { |env| + [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321') + + response.status.should.equal 200 + response.body.should.equal 'TEST' + end + + should "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do + timestamp = Time.now.httpdate + app = Rack::ConditionalGet.new(lambda { |env| + [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234') + + response.status.should.equal 304 + response.body.should.be.empty + end + + should "not affect non-GET/HEAD requests" do + app = Rack::ConditionalGet.new(lambda { |env| + [200, {'Etag'=>'1234'}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + post("/", 'HTTP_IF_NONE_MATCH' => '1234') + + response.status.should.equal 200 + response.body.should.equal 'TEST' + end + + should "not affect non-200 requests" do + app = Rack::ConditionalGet.new(lambda { |env| + [302, {'Etag'=>'1234'}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_NONE_MATCH' => '1234') + + response.status.should.equal 302 + response.body.should.equal 'TEST' + end + + should "not affect requests with malformed HTTP_IF_NONE_MATCH" do + bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z') + app = Rack::ConditionalGet.new(lambda { |env| + [200,{'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] }) + + response = Rack::MockRequest.new(app). + get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp) + + response.status.should.equal 200 + response.body.should.equal 'TEST' + end + +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_config.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_config.rb new file mode 100644 index 0000000..21425dd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_config.rb @@ -0,0 +1,23 @@ +require 'rack/builder' +require 'rack/config' +require 'rack/content_length' +require 'rack/lint' +require 'rack/mock' + +describe Rack::Config do + should "accept a block that modifies the environment" do + app = Rack::Builder.new do + use Rack::Lint + use Rack::ContentLength + use Rack::Config do |env| + env['greeting'] = 'hello' + end + run lambda { |env| + [200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']] + } + end + + response = Rack::MockRequest.new(app).get('/') + response.body.should.equal('hello') + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_content_length.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_content_length.rb new file mode 100644 index 0000000..5e480ae --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_content_length.rb @@ -0,0 +1,73 @@ +require 'rack/content_length' + +describe Rack::ContentLength do + should "set Content-Length on Array bodies if none is set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } + response = Rack::ContentLength.new(app).call({}) + response[1]['Content-Length'].should.equal '13' + end + + should "not set Content-Length on variable length bodies" do + body = lambda { "Hello World!" } + def body.each ; yield call ; end + + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] } + response = Rack::ContentLength.new(app).call({}) + response[1]['Content-Length'].should.be.nil + end + + should "not change Content-Length if it is already set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] } + response = Rack::ContentLength.new(app).call({}) + response[1]['Content-Length'].should.equal '1' + end + + should "not set Content-Length on 304 responses" do + app = lambda { |env| [304, {'Content-Type' => 'text/plain'}, []] } + response = Rack::ContentLength.new(app).call({}) + response[1]['Content-Length'].should.equal nil + end + + should "not set Content-Length when Transfer-Encoding is chunked" do + app = lambda { |env| [200, {'Transfer-Encoding' => 'chunked'}, []] } + response = Rack::ContentLength.new(app).call({}) + response[1]['Content-Length'].should.equal nil + end + + # Using "Connection: close" for this is fairly contended. It might be useful + # to have some other way to signal this. + # + # should "not force a Content-Length when Connection:close" do + # app = lambda { |env| [200, {'Connection' => 'close'}, []] } + # response = Rack::ContentLength.new(app).call({}) + # response[1]['Content-Length'].should.equal nil + # end + + should "close bodies that need to be closed" do + body = Struct.new(:body) do + attr_reader :closed + def each; body.join; end + def close; @closed = true; end + def to_ary; end + end.new(%w[one two three]) + + app = lambda { |env| [200, {}, body] } + response = Rack::ContentLength.new(app).call({}) + body.closed.should.equal true + end + + should "support single-execute bodies" do + body = Struct.new(:body) do + def each + yield body.shift until body.empty? + end + def to_ary; end + end.new(%w[one two three]) + + app = lambda { |env| [200, {}, body] } + response = Rack::ContentLength.new(app).call({}) + expected = %w[one two three] + response[1]['Content-Length'].should.equal expected.join.size.to_s + response[2].should.equal expected + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_content_type.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_content_type.rb new file mode 100644 index 0000000..44b0ed1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_content_type.rb @@ -0,0 +1,29 @@ +require 'rack/content_type' + +describe Rack::ContentType do + should "set Content-Type to default text/html if none is set" do + app = lambda { |env| [200, {}, "Hello, World!"] } + headers = Rack::ContentType.new(app).call({})[1] + headers['Content-Type'].should.equal 'text/html' + end + + should "set Content-Type to chosen default if none is set" do + app = lambda { |env| [200, {}, "Hello, World!"] } + headers = + Rack::ContentType.new(app, 'application/octet-stream').call({})[1] + headers['Content-Type'].should.equal 'application/octet-stream' + end + + should "not change Content-Type if it is already set" do + app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] } + headers = Rack::ContentType.new(app).call({})[1] + headers['Content-Type'].should.equal 'foo/bar' + end + + should "detect Content-Type case insensitive" do + app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] } + headers = Rack::ContentType.new(app).call({})[1] + headers.to_a.select { |k,v| k.downcase == "content-type" }. + should.equal [["CONTENT-Type","foo/bar"]] + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_deflater.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_deflater.rb new file mode 100644 index 0000000..0c9d060 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_deflater.rb @@ -0,0 +1,169 @@ +require 'stringio' +require 'time' # for Time#httpdate +require 'rack/deflater' +require 'rack/mock' +require 'zlib' + +describe Rack::Deflater do + def build_response(status, body, accept_encoding, headers = {}) + body = [body] if body.respond_to? :to_str + app = lambda { |env| [status, {}, body] } + request = Rack::MockRequest.env_for("", headers.merge("HTTP_ACCEPT_ENCODING" => accept_encoding)) + response = Rack::Deflater.new(app).call(request) + + return response + end + + def inflate(buf) + inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) + inflater.inflate(buf) << inflater.finish + end + + should "be able to deflate bodies that respond to each" do + body = Object.new + class << body; def each; yield("foo"); yield("bar"); end; end + + response = build_response(200, body, "deflate") + + response[0].should.equal(200) + response[1].should.equal({ + "Content-Encoding" => "deflate", + "Vary" => "Accept-Encoding" + }) + buf = '' + response[2].each { |part| buf << part } + inflate(buf).should.equal("foobar") + end + + should "flush deflated chunks to the client as they become ready" do + body = Object.new + class << body; def each; yield("foo"); yield("bar"); end; end + + response = build_response(200, body, "deflate") + + response[0].should.equal(200) + response[1].should.equal({ + "Content-Encoding" => "deflate", + "Vary" => "Accept-Encoding" + }) + buf = [] + inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) + response[2].each { |part| buf << inflater.inflate(part) } + buf << inflater.finish + buf.delete_if { |part| part.empty? } + buf.should.equal(%w(foo bar)) + end + + # TODO: This is really just a special case of the above... + should "be able to deflate String bodies" do + response = build_response(200, "Hello world!", "deflate") + + response[0].should.equal(200) + response[1].should.equal({ + "Content-Encoding" => "deflate", + "Vary" => "Accept-Encoding" + }) + buf = '' + response[2].each { |part| buf << part } + inflate(buf).should.equal("Hello world!") + end + + should "be able to gzip bodies that respond to each" do + body = Object.new + class << body; def each; yield("foo"); yield("bar"); end; end + + response = build_response(200, body, "gzip") + + response[0].should.equal(200) + response[1].should.equal({ + "Content-Encoding" => "gzip", + "Vary" => "Accept-Encoding", + }) + + buf = '' + response[2].each { |part| buf << part } + io = StringIO.new(buf) + gz = Zlib::GzipReader.new(io) + gz.read.should.equal("foobar") + gz.close + end + + should "flush gzipped chunks to the client as they become ready" do + body = Object.new + class << body; def each; yield("foo"); yield("bar"); end; end + + response = build_response(200, body, "gzip") + + response[0].should.equal(200) + response[1].should.equal({ + "Content-Encoding" => "gzip", + "Vary" => "Accept-Encoding" + }) + buf = [] + inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32) + response[2].each { |part| buf << inflater.inflate(part) } + buf << inflater.finish + buf.delete_if { |part| part.empty? } + buf.should.equal(%w(foo bar)) + end + + should "be able to fallback to no deflation" do + response = build_response(200, "Hello world!", "superzip") + + response[0].should.equal(200) + response[1].should.equal({ "Vary" => "Accept-Encoding" }) + response[2].should.equal(["Hello world!"]) + end + + should "be able to skip when there is no response entity body" do + response = build_response(304, [], "gzip") + + response[0].should.equal(304) + response[1].should.equal({}) + response[2].should.equal([]) + end + + should "handle the lack of an acceptable encoding" do + response1 = build_response(200, "Hello world!", "identity;q=0", "PATH_INFO" => "/") + response1[0].should.equal(406) + response1[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "71"}) + response1[2].should.equal(["An acceptable encoding for the requested resource / could not be found."]) + + response2 = build_response(200, "Hello world!", "identity;q=0", "SCRIPT_NAME" => "/foo", "PATH_INFO" => "/bar") + response2[0].should.equal(406) + response2[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "78"}) + response2[2].should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."]) + end + + should "handle gzip response with Last-Modified header" do + last_modified = Time.now.httpdate + + app = lambda { |env| [200, { "Last-Modified" => last_modified }, ["Hello World!"]] } + request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip") + response = Rack::Deflater.new(app).call(request) + + response[0].should.equal(200) + response[1].should.equal({ + "Content-Encoding" => "gzip", + "Vary" => "Accept-Encoding", + "Last-Modified" => last_modified + }) + + buf = '' + response[2].each { |part| buf << part } + io = StringIO.new(buf) + gz = Zlib::GzipReader.new(io) + gz.read.should.equal("Hello World!") + gz.close + end + + should "do nothing when no-transform Cache-Control directive present" do + app = lambda { |env| [200, {'Cache-Control' => 'no-transform'}, ['Hello World!']] } + request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip") + response = Rack::Deflater.new(app).call(request) + + response[0].should.equal(200) + response[1].should.not.include "Content-Encoding" + response[2].join.should.equal("Hello World!") + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_directory.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_directory.rb new file mode 100644 index 0000000..a45ba23 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_directory.rb @@ -0,0 +1,57 @@ +require 'rack/directory' +require 'rack/mock' + +describe Rack::Directory do + DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT + FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] } + app = Rack::Directory.new DOCROOT, FILE_CATCH + + should "serve directory indices" do + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/cgi/") + + res.should.be.ok + res.should =~ // + end + + should "pass to app if file found" do + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/cgi/test") + + res.should.be.ok + res.should =~ /passed!/ + end + + should "serve uri with URL encoded filenames" do + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/%63%67%69/") # "/cgi/test" + + res.should.be.ok + res.should =~ // + + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/cgi/%74%65%73%74") # "/cgi/test" + + res.should.be.ok + res.should =~ /passed!/ + end + + should "not allow directory traversal" do + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/cgi/../test") + + res.should.be.forbidden + + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/cgi/%2E%2E/test") + + res.should.be.forbidden + end + + should "404 if it can't find the file" do + res = Rack::MockRequest.new(Rack::Lint.new(app)). + get("/cgi/blubb") + + res.should.be.not_found + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_etag.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_etag.rb new file mode 100644 index 0000000..b01bb46 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_etag.rb @@ -0,0 +1,82 @@ +require 'rack/etag' +require 'time' + +describe Rack::ETag do + def sendfile_body + res = ['Hello World'] + def res.to_path ; "/tmp/hello.txt" ; end + res + end + + should "set ETag if none is set if status is 200" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\"" + end + + should "set ETag if none is set if status is 201" do + app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\"" + end + + should "set Cache-Control to 'max-age=0, private, must-revalidate' (default) if none is set" do + app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['Cache-Control'].should.equal 'max-age=0, private, must-revalidate' + end + + should "set Cache-Control to chosen one if none is set" do + app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } + response = Rack::ETag.new(app, nil, 'public').call({}) + response[1]['Cache-Control'].should.equal 'public' + end + + should "set a given Cache-Control even if digest could not be calculated" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, []] } + response = Rack::ETag.new(app, 'no-cache').call({}) + response[1]['Cache-Control'].should.equal 'no-cache' + end + + should "not set Cache-Control if it is already set" do + app = lambda { |env| [201, {'Content-Type' => 'text/plain', 'Cache-Control' => 'public'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['Cache-Control'].should.equal 'public' + end + + should "not change ETag if it is already set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.equal "\"abc\"" + end + + should "not set ETag if body is empty" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, []] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.be.nil + end + + should "not set ETag if Last-Modified is set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.be.nil + end + + should "not set ETag if a sendfile_body is given" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, sendfile_body] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.be.nil + end + + should "not set ETag if a status is not 200 or 201" do + app = lambda { |env| [401, {'Content-Type' => 'text/plain'}, ['Access denied.']] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.be.nil + end + + should "not set ETag if no-cache is given" do + app = lambda { |env| [200, {'Cache-Control' => 'no-cache'}, ['Hello, World!']] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.be.nil + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_fastcgi.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_fastcgi.rb new file mode 100644 index 0000000..93df4d1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_fastcgi.rb @@ -0,0 +1,107 @@ +begin +require File.expand_path('../testrequest', __FILE__) +require 'rack/handler/fastcgi' + +describe Rack::Handler::FastCGI do + extend TestRequest::Helpers + + @host = '0.0.0.0' + @port = 9203 + + if `which lighttpd` && !$?.success? + raise "lighttpd not found" + end + + # Keep this first. + $pid = fork { + ENV['RACK_ENV'] = 'deployment' + ENV['RUBYLIB'] = [ + File.expand_path('../../lib', __FILE__), + ENV['RUBYLIB'], + ].compact.join(':') + + Dir.chdir(File.expand_path("../cgi", __FILE__)) do + exec "lighttpd -D -f lighttpd.conf" + end + } + + should "respond" do + sleep 1 + GET("/test") + response.should.not.be.nil + end + + should "respond via rackup server" do + GET("/sample_rackup.ru") + status.should.equal 200 + end + + should "be a lighttpd" do + GET("/test.fcgi") + status.should.equal 200 + response["SERVER_SOFTWARE"].should =~ /lighttpd/ + response["HTTP_VERSION"].should.equal "HTTP/1.1" + response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" + response["SERVER_PORT"].should.equal @port.to_s + response["SERVER_NAME"].should.equal @host + end + + should "have rack headers" do + GET("/test.fcgi") + response["rack.version"].should.equal [1,1] + response["rack.multithread"].should.be.false + response["rack.multiprocess"].should.be.true + response["rack.run_once"].should.be.false + end + + should "have CGI headers on GET" do + GET("/test.fcgi") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test.fcgi" + response["REQUEST_PATH"].should.equal "/" + response["PATH_INFO"].should.equal "" + response["QUERY_STRING"].should.equal "" + response["test.postdata"].should.equal "" + + GET("/test.fcgi/foo?quux=1") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test.fcgi" + response["REQUEST_PATH"].should.equal "/" + response["PATH_INFO"].should.equal "/foo" + response["QUERY_STRING"].should.equal "quux=1" + end + + should "have CGI headers on POST" do + POST("/test.fcgi", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) + status.should.equal 200 + response["REQUEST_METHOD"].should.equal "POST" + response["SCRIPT_NAME"].should.equal "/test.fcgi" + response["REQUEST_PATH"].should.equal "/" + response["QUERY_STRING"].should.equal "" + response["HTTP_X_TEST_HEADER"].should.equal "42" + response["test.postdata"].should.equal "rack-form-data=23" + end + + should "support HTTP auth" do + GET("/test.fcgi", {:user => "ruth", :passwd => "secret"}) + response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" + end + + should "set status" do + GET("/test.fcgi?secret") + status.should.equal 403 + response["rack.url_scheme"].should.equal "http" + end + + # Keep this last. + should "shutdown" do + Process.kill 15, $pid + Process.wait($pid).should.equal $pid + end +end + +rescue RuntimeError + $stderr.puts "Skipping Rack::Handler::FastCGI tests (lighttpd is required). Install lighttpd and try again." +rescue LoadError + $stderr.puts "Skipping Rack::Handler::FastCGI tests (FCGI is required). `gem install fcgi` and try again." +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_file.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_file.rb new file mode 100644 index 0000000..121e5a2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_file.rb @@ -0,0 +1,122 @@ +require 'rack/file' +require 'rack/mock' + +describe Rack::File do + DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT + + should "serve files" do + res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))). + get("/cgi/test") + + res.should.be.ok + res.should =~ /ruby/ + end + + should "set Last-Modified header" do + res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))). + get("/cgi/test") + + path = File.join(DOCROOT, "/cgi/test") + + res.should.be.ok + res["Last-Modified"].should.equal File.mtime(path).httpdate + end + + should "serve files with URL encoded filenames" do + res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))). + get("/cgi/%74%65%73%74") # "/cgi/test" + + res.should.be.ok + res.should =~ /ruby/ + end + + should "not allow directory traversal" do + req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))) + res = req.get("/cgi/../test") + res.should.be.forbidden + + res = req.get("../test") + res.should.be.forbidden + + res = req.get("..") + res.should.be.forbidden + + res = req.get("test/..") + res.should.be.forbidden + end + + should "allow files with .. in their name" do + req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))) + res = req.get("/cgi/..test") + res.should.be.not_found + + res = req.get("/cgi/test..") + res.should.be.not_found + + res = req.get("/cgi../test..") + res.should.be.not_found + end + + should "not allow directory traversal with encoded periods" do + res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))). + get("/%2E%2E/README") + + res.should.be.forbidden + end + + should "404 if it can't find the file" do + res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))). + get("/cgi/blubb") + + res.should.be.not_found + end + + should "detect SystemCallErrors" do + res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))). + get("/cgi") + + res.should.be.not_found + end + + should "return bodies that respond to #to_path" do + env = Rack::MockRequest.env_for("/cgi/test") + status, _, body = Rack::File.new(DOCROOT).call(env) + + path = File.join(DOCROOT, "/cgi/test") + + status.should.equal 200 + body.should.respond_to :to_path + body.to_path.should.equal path + end + + should "return correct byte range in body" do + env = Rack::MockRequest.env_for("/cgi/test") + env["HTTP_RANGE"] = "bytes=22-33" + res = Rack::MockResponse.new(*Rack::File.new(DOCROOT).call(env)) + + res.status.should.equal 206 + res["Content-Length"].should.equal "12" + res["Content-Range"].should.equal "bytes 22-33/193" + res.body.should.equal "-*- ruby -*-" + end + + should "return error for unsatisfiable byte range" do + env = Rack::MockRequest.env_for("/cgi/test") + env["HTTP_RANGE"] = "bytes=1234-5678" + res = Rack::MockResponse.new(*Rack::File.new(DOCROOT).call(env)) + + res.status.should.equal 416 + res["Content-Range"].should.equal "bytes */193" + end + + should "support cache control options" do + env = Rack::MockRequest.env_for("/cgi/test") + status, heads, _ = Rack::File.new(DOCROOT, 'public, max-age=38').call(env) + + path = File.join(DOCROOT, "/cgi/test") + + status.should.equal 200 + heads['Cache-Control'].should.equal 'public, max-age=38' + end + +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_handler.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_handler.rb new file mode 100644 index 0000000..e8f41fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_handler.rb @@ -0,0 +1,59 @@ +require 'rack/handler' + +class Rack::Handler::Lobster; end +class RockLobster; end + +describe Rack::Handler do + it "has registered default handlers" do + Rack::Handler.get('cgi').should.equal Rack::Handler::CGI + Rack::Handler.get('webrick').should.equal Rack::Handler::WEBrick + + begin + Rack::Handler.get('fastcgi').should.equal Rack::Handler::FastCGI + rescue LoadError + end + + begin + Rack::Handler.get('mongrel').should.equal Rack::Handler::Mongrel + rescue LoadError + end + end + + should "raise LoadError if handler doesn't exist" do + lambda { + Rack::Handler.get('boom') + }.should.raise(LoadError) + end + + should "get unregistered, but already required, handler by name" do + Rack::Handler.get('Lobster').should.equal Rack::Handler::Lobster + end + + should "register custom handler" do + Rack::Handler.register('rock_lobster', 'RockLobster') + Rack::Handler.get('rock_lobster').should.equal RockLobster + end + + should "not need registration for properly coded handlers even if not already required" do + begin + $LOAD_PATH.push File.expand_path('../unregistered_handler', __FILE__) + Rack::Handler.get('Unregistered').should.equal Rack::Handler::Unregistered + lambda { + Rack::Handler.get('UnRegistered') + }.should.raise LoadError + Rack::Handler.get('UnregisteredLongOne').should.equal Rack::Handler::UnregisteredLongOne + ensure + $LOAD_PATH.delete File.expand_path('../unregistered_handler', __FILE__) + end + end + + should "allow autoloaded handlers to be registered properly while being loaded" do + path = File.expand_path('../registering_handler', __FILE__) + begin + $LOAD_PATH.push path + Rack::Handler.get('registering_myself').should.equal Rack::Handler::RegisteringMyself + ensure + $LOAD_PATH.delete path + end + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_head.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_head.rb new file mode 100644 index 0000000..f81392a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_head.rb @@ -0,0 +1,30 @@ +require 'rack/head' +require 'rack/mock' + +describe Rack::Head do + def test_response(headers = {}) + app = lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] } + request = Rack::MockRequest.env_for("/", headers) + response = Rack::Head.new(app).call(request) + + return response + end + + should "pass GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do + %w[GET POST PUT DELETE OPTIONS TRACE].each do |type| + resp = test_response("REQUEST_METHOD" => type) + + resp[0].should.equal(200) + resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"}) + resp[2].should.equal(["foo"]) + end + end + + should "remove body from HEAD requests" do + resp = test_response("REQUEST_METHOD" => "HEAD") + + resp[0].should.equal(200) + resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"}) + resp[2].should.equal([]) + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lint.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lint.rb new file mode 100644 index 0000000..eda0dfc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lint.rb @@ -0,0 +1,515 @@ +require 'stringio' +require 'rack/lint' +require 'rack/mock' + +describe Rack::Lint do + def env(*args) + Rack::MockRequest.env_for("/", *args) + end + + should "pass valid request" do + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] + }).call(env({})) + }.should.not.raise + end + + should "notice fatal errors" do + lambda { Rack::Lint.new(nil).call }.should.raise(Rack::Lint::LintError). + message.should.match(/No env given/) + end + + should "notice environment errors" do + lambda { Rack::Lint.new(nil).call 5 }.should.raise(Rack::Lint::LintError). + message.should.match(/not a Hash/) + + lambda { + e = env + e.delete("REQUEST_METHOD") + Rack::Lint.new(nil).call(e) + }.should.raise(Rack::Lint::LintError). + message.should.match(/missing required key REQUEST_METHOD/) + + lambda { + e = env + e.delete("SERVER_NAME") + Rack::Lint.new(nil).call(e) + }.should.raise(Rack::Lint::LintError). + message.should.match(/missing required key SERVER_NAME/) + + + lambda { + Rack::Lint.new(nil).call(env("HTTP_CONTENT_TYPE" => "text/plain")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/contains HTTP_CONTENT_TYPE/) + + lambda { + Rack::Lint.new(nil).call(env("HTTP_CONTENT_LENGTH" => "42")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/contains HTTP_CONTENT_LENGTH/) + + lambda { + Rack::Lint.new(nil).call(env("FOO" => Object.new)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/non-string value/) + + lambda { + Rack::Lint.new(nil).call(env("rack.version" => "0.2")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must be an Array/) + + lambda { + Rack::Lint.new(nil).call(env("rack.url_scheme" => "gopher")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/url_scheme unknown/) + + lambda { + Rack::Lint.new(nil).call(env("rack.session" => [])) + }.should.raise(Rack::Lint::LintError). + message.should.equal("session [] must respond to store and []=") + + lambda { + Rack::Lint.new(nil).call(env("rack.logger" => [])) + }.should.raise(Rack::Lint::LintError). + message.should.equal("logger [] must respond to info") + + lambda { + Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/REQUEST_METHOD/) + + lambda { + Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must start with/) + + lambda { + Rack::Lint.new(nil).call(env("PATH_INFO" => "../foo")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must start with/) + + lambda { + Rack::Lint.new(nil).call(env("CONTENT_LENGTH" => "xcii")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/Invalid CONTENT_LENGTH/) + + lambda { + e = env + e.delete("PATH_INFO") + e.delete("SCRIPT_NAME") + Rack::Lint.new(nil).call(e) + }.should.raise(Rack::Lint::LintError). + message.should.match(/One of .* must be set/) + + lambda { + Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "/")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/cannot be .* make it ''/) + end + + should "notice input errors" do + lambda { + Rack::Lint.new(nil).call(env("rack.input" => "")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/does not respond to #gets/) + + lambda { + input = Object.new + def input.binmode? + false + end + Rack::Lint.new(nil).call(env("rack.input" => input)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/is not opened in binary mode/) + + lambda { + input = Object.new + def input.external_encoding + result = Object.new + def result.name + "US-ASCII" + end + result + end + Rack::Lint.new(nil).call(env("rack.input" => input)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/does not have ASCII-8BIT as its external encoding/) + end + + should "notice error errors" do + lambda { + Rack::Lint.new(nil).call(env("rack.errors" => "")) + }.should.raise(Rack::Lint::LintError). + message.should.match(/does not respond to #puts/) + end + + should "notice status errors" do + lambda { + Rack::Lint.new(lambda { |env| + ["cc", {}, ""] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must be >=100 seen as integer/) + + lambda { + Rack::Lint.new(lambda { |env| + [42, {}, ""] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must be >=100 seen as integer/) + end + + should "notice header errors" do + lambda { + Rack::Lint.new(lambda { |env| + [200, Object.new, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.equal("headers object should respond to #each, but doesn't (got Object as headers)") + + lambda { + Rack::Lint.new(lambda { |env| + [200, {true=>false}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.equal("header key must be a string, was TrueClass") + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Status" => "404"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must not contain Status/) + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-Type:" => "text/plain"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must not contain :/) + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-" => "text/plain"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/must not end/) + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"..%%quark%%.." => "text/plain"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.equal("invalid header name: ..%%quark%%..") + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Foo" => Object.new}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.equal("a header value must be a String, but the value of 'Foo' is a Object") + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Foo" => [1, 2, 3]}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.equal("a header value must be a String, but the value of 'Foo' is a Array") + + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Foo-Bar" => "text\000plain"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/invalid header/) + + # line ends (010) should be allowed in header values. + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []] + }).call(env({})) + }.should.not.raise(Rack::Lint::LintError) + end + + should "notice content-type errors" do + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/No Content-Type/) + + [100, 101, 204, 304].each do |status| + lambda { + Rack::Lint.new(lambda { |env| + [status, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/Content-Type header found/) + end + end + + should "notice content-length errors" do + [100, 101, 204, 304].each do |status| + lambda { + Rack::Lint.new(lambda { |env| + [status, {"Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/Content-Length header found/) + end + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []] + }).call(env({}))[2].each { } + }.should.raise(Rack::Lint::LintError). + message.should.match(/Content-Length header was 1, but should be 0/) + end + + should "notice body errors" do + lambda { + body = Rack::Lint.new(lambda { |env| + [200, {"Content-type" => "text/plain","Content-length" => "3"}, [1,2,3]] + }).call(env({}))[2] + body.each { |part| } + }.should.raise(Rack::Lint::LintError). + message.should.match(/yielded non-string/) + end + + should "notice input handling errors" do + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].gets("\r\n") + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/gets called with arguments/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(1, 2, 3) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read called with too many arguments/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read("foo") + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read called with non-integer and non-nil length/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(-1) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read called with a negative length/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(nil, nil) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read called with non-String buffer/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(nil, 1) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read called with non-String buffer/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].rewind(0) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/rewind called with arguments/) + + weirdio = Object.new + class << weirdio + def gets + 42 + end + + def read + 23 + end + + def each + yield 23 + yield 42 + end + + def rewind + raise Errno::ESPIPE, "Errno::ESPIPE" + end + end + + eof_weirdio = Object.new + class << eof_weirdio + def gets + nil + end + + def read(*args) + nil + end + + def each + end + + def rewind + end + end + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].gets + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env("rack.input" => weirdio)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/gets didn't return a String/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].each { |x| } + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env("rack.input" => weirdio)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/each didn't yield a String/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env("rack.input" => weirdio)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read didn't return nil or a String/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env("rack.input" => eof_weirdio)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/read\(nil\) returned nil on EOF/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].rewind + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env("rack.input" => weirdio)) + }.should.raise(Rack::Lint::LintError). + message.should.match(/rewind raised Errno::ESPIPE/) + + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].close + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/close must not be called/) + end + + should "notice error handling errors" do + lambda { + Rack::Lint.new(lambda { |env| + env["rack.errors"].write(42) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/write not called with a String/) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.errors"].close + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({})) + }.should.raise(Rack::Lint::LintError). + message.should.match(/close must not be called/) + end + + should "notice HEAD errors" do + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []] + }).call(env({"REQUEST_METHOD" => "HEAD"})) + }.should.not.raise + + lambda { + Rack::Lint.new(lambda { |env| + [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] + }).call(env({"REQUEST_METHOD" => "HEAD"}))[2].each { } + }.should.raise(Rack::Lint::LintError). + message.should.match(/body was given for HEAD/) + end + + should "pass valid read calls" do + hello_str = "hello world" + hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({"rack.input" => StringIO.new(hello_str)})) + }.should.not.raise(Rack::Lint::LintError) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(0) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({"rack.input" => StringIO.new(hello_str)})) + }.should.not.raise(Rack::Lint::LintError) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(1) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({"rack.input" => StringIO.new(hello_str)})) + }.should.not.raise(Rack::Lint::LintError) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(nil) + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({"rack.input" => StringIO.new(hello_str)})) + }.should.not.raise(Rack::Lint::LintError) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(nil, '') + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({"rack.input" => StringIO.new(hello_str)})) + }.should.not.raise(Rack::Lint::LintError) + + lambda { + Rack::Lint.new(lambda { |env| + env["rack.input"].read(1, '') + [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []] + }).call(env({"rack.input" => StringIO.new(hello_str)})) + }.should.not.raise(Rack::Lint::LintError) + end +end + +describe "Rack::Lint::InputWrapper" do + should "delegate :rewind to underlying IO object" do + io = StringIO.new("123") + wrapper = Rack::Lint::InputWrapper.new(io) + wrapper.read.should.equal "123" + wrapper.read.should.equal "" + wrapper.rewind + wrapper.read.should.equal "123" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lobster.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lobster.rb new file mode 100644 index 0000000..6a61040 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lobster.rb @@ -0,0 +1,43 @@ +require 'rack/lobster' +require 'rack/mock' + +describe Rack::Lobster::LambdaLobster do + should "be a single lambda" do + Rack::Lobster::LambdaLobster.should.be.kind_of Proc + end + + should "look like a lobster" do + res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/") + res.should.be.ok + res.body.should.include "(,(,,(,,,(" + res.body.should.include "?flip" + end + + should "be flippable" do + res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/?flip") + res.should.be.ok + res.body.should.include "(,,,(,,(,(" + end +end + +describe Rack::Lobster do + should "look like a lobster" do + res = Rack::MockRequest.new(Rack::Lobster.new).get("/") + res.should.be.ok + res.body.should.include "(,(,,(,,,(" + res.body.should.include "?flip" + res.body.should.include "crash" + end + + should "be flippable" do + res = Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=left") + res.should.be.ok + res.body.should.include "(,,,(,,(,(" + end + + should "provide crashing for testing purposes" do + lambda { + Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=crash") + }.should.raise + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lock.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lock.rb new file mode 100644 index 0000000..6484909 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_lock.rb @@ -0,0 +1,142 @@ +require 'rack/lock' +require 'rack/mock' + +class Lock + attr_reader :synchronized + + def initialize + @synchronized = false + end + + def synchronize + @synchronized = true + yield + end + + def lock + @synchronized = true + end + + def unlock + @synchronized = false + end +end + +describe Rack::Lock do + describe 'Proxy' do + should 'delegate each' do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + response = Class.new { + attr_accessor :close_called + def initialize; @close_called = false; end + def each; %w{ hi mom }.each { |x| yield x }; end + }.new + + app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock) + response = app.call(env)[2] + list = [] + response.each { |x| list << x } + list.should.equal %w{ hi mom } + end + + should 'delegate to_path' do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + + res = ['Hello World'] + def res.to_path ; "/tmp/hello.txt" ; end + + app = Rack::Lock.new(lambda { |inner_env| [200, {}, res] }, lock) + body = app.call(env)[2] + + body.should.respond_to :to_path + body.to_path.should.equal "/tmp/hello.txt" + end + + should 'not delegate to_path if body does not implement it' do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + + res = ['Hello World'] + + app = Rack::Lock.new(lambda { |inner_env| [200, {}, res] }, lock) + body = app.call(env)[2] + + body.should.not.respond_to :to_path + end + end + + should 'call super on close' do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + response = Class.new { + attr_accessor :close_called + def initialize; @close_called = false; end + def close; @close_called = true; end + }.new + + app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock) + app.call(env) + response.close_called.should.equal false + response.close + response.close_called.should.equal true + end + + should "not unlock until body is closed" do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + response = Object.new + app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock) + lock.synchronized.should.equal false + response = app.call(env)[2] + lock.synchronized.should.equal true + response.close + lock.synchronized.should.equal false + end + + should "return value from app" do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + body = [200, {}, %w{ hi mom }] + app = Rack::Lock.new(lambda { |inner_env| body }, lock) + app.call(env).should.equal body + end + + should "call synchronize on lock" do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + app = Rack::Lock.new(lambda { |inner_env| + [200, {}, %w{ a b c }] + }, lock) + lock.synchronized.should.equal false + app.call(env) + lock.synchronized.should.equal true + end + + should "unlock if the app raises" do + lock = Lock.new + env = Rack::MockRequest.env_for("/") + app = Rack::Lock.new(lambda { raise Exception }, lock) + lambda { app.call(env) }.should.raise(Exception) + lock.synchronized.should.equal false + end + + should "set multithread flag to false" do + app = Rack::Lock.new(lambda { |env| + env['rack.multithread'].should.equal false + [200, {}, %w{ a b c }] + }) + app.call(Rack::MockRequest.env_for("/")) + end + + should "reset original multithread flag when exiting lock" do + app = Class.new(Rack::Lock) { + def call(env) + env['rack.multithread'].should.equal true + super + end + }.new(lambda { |env| [200, {}, %w{ a b c }] }) + app.call(Rack::MockRequest.env_for("/")) + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_logger.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_logger.rb new file mode 100644 index 0000000..f9e7973 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_logger.rb @@ -0,0 +1,28 @@ +require 'stringio' +require 'rack/logger' + +describe Rack::Logger do + app = lambda { |env| + log = env['rack.logger'] + log.debug("Created logger") + log.info("Program started") + log.warn("Nothing to do!") + + [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] + } + + should "log to rack.errors" do + errors = StringIO.new + Rack::Logger.new(app).call('rack.errors' => errors) + errors.string.should.match(/INFO -- : Program started/) + errors.string.should.match(/WARN -- : Nothing to do/) + end + + should "conform to Rack::Lint" do + errors = StringIO.new + a = Rack::Lint.new(Rack::Logger.new(app)) + Rack::MockRequest.new(a).get('/', 'rack.errors' => errors) + errors.string.should.match(/INFO -- : Program started/) + errors.string.should.match(/WARN -- : Nothing to do/) + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_methodoverride.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_methodoverride.rb new file mode 100644 index 0000000..82c6cbd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_methodoverride.rb @@ -0,0 +1,58 @@ +require 'stringio' +require 'rack/methodoverride' +require 'rack/mock' + +describe Rack::MethodOverride do + should "not affect GET requests" do + env = Rack::MockRequest.env_for("/?_method=delete", :method => "GET") + app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "GET" + end + + should "modify REQUEST_METHOD for POST requests when _method parameter is set" do + env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put") + app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "PUT" + end + + should "modify REQUEST_METHOD for POST requests when X-HTTP-Method-Override is set" do + env = Rack::MockRequest.env_for("/", + :method => "POST", + "HTTP_X_HTTP_METHOD_OVERRIDE" => "PATCH" + ) + app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "PATCH" + end + + should "not modify REQUEST_METHOD if the method is unknown" do + env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo") + app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "POST" + end + + should "not modify REQUEST_METHOD when _method is nil" do + env = Rack::MockRequest.env_for("/", :method => "POST", :input => "foo=bar") + app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "POST" + end + + should "store the original REQUEST_METHOD prior to overriding" do + env = Rack::MockRequest.env_for("/", + :method => "POST", + :input => "_method=options") + app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) }) + req = app.call(env) + + req.env["rack.methodoverride.original_method"].should.equal "POST" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_mock.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_mock.rb new file mode 100644 index 0000000..61fc56a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_mock.rb @@ -0,0 +1,260 @@ +require 'yaml' +require 'rack/mock' +require 'stringio' + +app = lambda { |env| + req = Rack::Request.new(env) + + env["mock.postdata"] = env["rack.input"].read + if req.GET["error"] + env["rack.errors"].puts req.GET["error"] + env["rack.errors"].flush + end + + Rack::Response.new(env.to_yaml, + req.GET["status"] || 200, + "Content-Type" => "text/yaml").finish +} + +describe Rack::MockRequest do + should "return a MockResponse" do + res = Rack::MockRequest.new(app).get("") + res.should.be.kind_of Rack::MockResponse + end + + should "be able to only return the environment" do + env = Rack::MockRequest.env_for("") + env.should.be.kind_of Hash + env.should.include "rack.version" + end + + should "provide sensible defaults" do + res = Rack::MockRequest.new(app).request + + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + env["SERVER_NAME"].should.equal "example.org" + env["SERVER_PORT"].should.equal "80" + env["QUERY_STRING"].should.equal "" + env["PATH_INFO"].should.equal "/" + env["SCRIPT_NAME"].should.equal "" + env["rack.url_scheme"].should.equal "http" + env["mock.postdata"].should.be.empty + end + + should "allow GET/POST/PUT/DELETE" do + res = Rack::MockRequest.new(app).get("", :input => "foo") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + + res = Rack::MockRequest.new(app).post("", :input => "foo") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "POST" + + res = Rack::MockRequest.new(app).put("", :input => "foo") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "PUT" + + res = Rack::MockRequest.new(app).delete("", :input => "foo") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "DELETE" + + Rack::MockRequest.env_for("/", :method => "OPTIONS")["REQUEST_METHOD"]. + should.equal "OPTIONS" + end + + should "set content length" do + env = Rack::MockRequest.env_for("/", :input => "foo") + env["CONTENT_LENGTH"].should.equal "3" + end + + should "allow posting" do + res = Rack::MockRequest.new(app).get("", :input => "foo") + env = YAML.load(res.body) + env["mock.postdata"].should.equal "foo" + + res = Rack::MockRequest.new(app).post("", :input => StringIO.new("foo")) + env = YAML.load(res.body) + env["mock.postdata"].should.equal "foo" + end + + should "use all parts of an URL" do + res = Rack::MockRequest.new(app). + get("https://bla.example.org:9292/meh/foo?bar") + res.should.be.kind_of Rack::MockResponse + + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + env["SERVER_NAME"].should.equal "bla.example.org" + env["SERVER_PORT"].should.equal "9292" + env["QUERY_STRING"].should.equal "bar" + env["PATH_INFO"].should.equal "/meh/foo" + env["rack.url_scheme"].should.equal "https" + end + + should "set SSL port and HTTP flag on when using https" do + res = Rack::MockRequest.new(app). + get("https://example.org/foo") + res.should.be.kind_of Rack::MockResponse + + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + env["SERVER_NAME"].should.equal "example.org" + env["SERVER_PORT"].should.equal "443" + env["QUERY_STRING"].should.equal "" + env["PATH_INFO"].should.equal "/foo" + env["rack.url_scheme"].should.equal "https" + env["HTTPS"].should.equal "on" + end + + should "prepend slash to uri path" do + res = Rack::MockRequest.new(app). + get("foo") + res.should.be.kind_of Rack::MockResponse + + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + env["SERVER_NAME"].should.equal "example.org" + env["SERVER_PORT"].should.equal "80" + env["QUERY_STRING"].should.equal "" + env["PATH_INFO"].should.equal "/foo" + env["rack.url_scheme"].should.equal "http" + end + + should "properly convert method name to an uppercase string" do + res = Rack::MockRequest.new(app).request(:get) + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + end + + should "accept params and build query string for GET requests" do + res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}}) + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + env["QUERY_STRING"].should.include "baz=2" + env["QUERY_STRING"].should.include "foo[bar]=1" + env["PATH_INFO"].should.equal "/foo" + env["mock.postdata"].should.equal "" + end + + should "accept raw input in params for GET requests" do + res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "GET" + env["QUERY_STRING"].should.include "baz=2" + env["QUERY_STRING"].should.include "foo[bar]=1" + env["PATH_INFO"].should.equal "/foo" + env["mock.postdata"].should.equal "" + end + + should "accept params and build url encoded params for POST requests" do + res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}}) + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "POST" + env["QUERY_STRING"].should.equal "" + env["PATH_INFO"].should.equal "/foo" + env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded" + env["mock.postdata"].should.equal "foo[bar]=1" + end + + should "accept raw input in params for POST requests" do + res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "POST" + env["QUERY_STRING"].should.equal "" + env["PATH_INFO"].should.equal "/foo" + env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded" + env["mock.postdata"].should.equal "foo[bar]=1" + end + + should "accept params and build multipart encoded params for POST requests" do + files = Rack::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt")) + res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files }) + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "POST" + env["QUERY_STRING"].should.equal "" + env["PATH_INFO"].should.equal "/foo" + env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x" + # The gsub accounts for differences in YAMLs affect on the data. + env["mock.postdata"].gsub("\r", "").length.should.equal 206 + end + + should "behave valid according to the Rack spec" do + lambda { + Rack::MockRequest.new(app). + get("https://bla.example.org:9292/meh/foo?bar", :lint => true) + }.should.not.raise(Rack::Lint::LintError) + end + + should "call close on the original body object" do + called = false + body = Rack::BodyProxy.new(['hi']) { called = true } + capp = proc { |e| [200, {'Content-Type' => 'text/plain '}, body] } + called.should.equal false + Rack::MockRequest.new(capp).get('/', :lint => true) + called.should.equal true + end +end + +describe Rack::MockResponse do + should "provide access to the HTTP status" do + res = Rack::MockRequest.new(app).get("") + res.should.be.successful + res.should.be.ok + + res = Rack::MockRequest.new(app).get("/?status=404") + res.should.not.be.successful + res.should.be.client_error + res.should.be.not_found + + res = Rack::MockRequest.new(app).get("/?status=501") + res.should.not.be.successful + res.should.be.server_error + + res = Rack::MockRequest.new(app).get("/?status=307") + res.should.be.redirect + + res = Rack::MockRequest.new(app).get("/?status=201", :lint => true) + res.should.be.empty + end + + should "provide access to the HTTP headers" do + res = Rack::MockRequest.new(app).get("") + res.should.include "Content-Type" + res.headers["Content-Type"].should.equal "text/yaml" + res.original_headers["Content-Type"].should.equal "text/yaml" + res["Content-Type"].should.equal "text/yaml" + res.content_type.should.equal "text/yaml" + res.content_length.should.not.equal 0 + res.location.should.be.nil + end + + should "provide access to the HTTP body" do + res = Rack::MockRequest.new(app).get("") + res.body.should =~ /rack/ + res.should =~ /rack/ + res.should.match(/rack/) + res.should.satisfy { |r| r.match(/rack/) } + end + + should "provide access to the Rack errors" do + res = Rack::MockRequest.new(app).get("/?error=foo", :lint => true) + res.should.be.ok + res.errors.should.not.be.empty + res.errors.should.include "foo" + end + + should "allow calling body.close afterwards" do + # this is exactly what rack-test does + body = StringIO.new("hi") + res = Rack::MockResponse.new(200, {}, body) + body.close if body.respond_to?(:close) + res.body.should == 'hi' + end + + should "optionally make Rack errors fatal" do + lambda { + Rack::MockRequest.new(app).get("/?error=foo", :fatal => true) + }.should.raise(Rack::MockRequest::FatalWarning) + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_mongrel.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_mongrel.rb new file mode 100644 index 0000000..5361b5b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_mongrel.rb @@ -0,0 +1,182 @@ +begin +require 'rack' +require 'rack/handler/mongrel' +require File.expand_path('../testrequest', __FILE__) +require 'timeout' + +Thread.abort_on_exception = true +$tcp_defer_accept_opts = nil +$tcp_cork_opts = nil + +describe Rack::Handler::Mongrel do + extend TestRequest::Helpers + + @server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201) + @server.register('/test', + Rack::Handler::Mongrel.new(Rack::Lint.new(TestRequest.new))) + @server.register('/stream', + Rack::Handler::Mongrel.new(Rack::Lint.new(StreamingRequest))) + @acc = @server.run + + should "respond" do + lambda { + GET("/test") + }.should.not.raise + end + + should "be a Mongrel" do + GET("/test") + status.should.equal 200 + response["SERVER_SOFTWARE"].should =~ /Mongrel/ + response["HTTP_VERSION"].should.equal "HTTP/1.1" + response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" + response["SERVER_PORT"].should.equal "9201" + response["SERVER_NAME"].should.equal "0.0.0.0" + end + + should "have rack headers" do + GET("/test") + response["rack.version"].should.equal [1,1] + response["rack.multithread"].should.be.true + response["rack.multiprocess"].should.be.false + response["rack.run_once"].should.be.false + end + + should "have CGI headers on GET" do + GET("/test") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test" + response["PATH_INFO"].should.be.equal "" + response["QUERY_STRING"].should.equal "" + response["test.postdata"].should.equal "" + + GET("/test/foo?quux=1") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test/foo" + response["PATH_INFO"].should.equal "/foo" + response["QUERY_STRING"].should.equal "quux=1" + end + + should "have CGI headers on POST" do + POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) + status.should.equal 200 + response["REQUEST_METHOD"].should.equal "POST" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test" + response["QUERY_STRING"].should.equal "" + response["HTTP_X_TEST_HEADER"].should.equal "42" + response["test.postdata"].should.equal "rack-form-data=23" + end + + should "support HTTP auth" do + GET("/test", {:user => "ruth", :passwd => "secret"}) + response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" + end + + should "set status" do + GET("/test?secret") + status.should.equal 403 + response["rack.url_scheme"].should.equal "http" + end + + should "provide a .run" do + block_ran = false + Thread.new { + Rack::Handler::Mongrel.run(lambda {}, {:Port => 9211}) { |server| + server.should.be.kind_of Mongrel::HttpServer + block_ran = true + } + } + sleep 1 + block_ran.should.be.true + end + + should "provide a .run that maps a hash" do + block_ran = false + Thread.new { + map = {'/'=>lambda{},'/foo'=>lambda{}} + Rack::Handler::Mongrel.run(map, :map => true, :Port => 9221) { |server| + server.should.be.kind_of Mongrel::HttpServer + server.classifier.uris.size.should.equal 2 + server.classifier.uris.should.not.include '/arf' + server.classifier.uris.should.include '/' + server.classifier.uris.should.include '/foo' + block_ran = true + } + } + sleep 1 + block_ran.should.be.true + end + + should "provide a .run that maps a urlmap" do + block_ran = false + Thread.new { + map = Rack::URLMap.new({'/'=>lambda{},'/bar'=>lambda{}}) + Rack::Handler::Mongrel.run(map, {:map => true, :Port => 9231}) { |server| + server.should.be.kind_of Mongrel::HttpServer + server.classifier.uris.size.should.equal 2 + server.classifier.uris.should.not.include '/arf' + server.classifier.uris.should.include '/' + server.classifier.uris.should.include '/bar' + block_ran = true + } + } + sleep 1 + block_ran.should.be.true + end + + should "provide a .run that maps a urlmap restricting by host" do + block_ran = false + Thread.new { + map = Rack::URLMap.new({ + '/' => lambda{}, + '/foo' => lambda{}, + '/bar' => lambda{}, + 'http://localhost/' => lambda{}, + 'http://localhost/bar' => lambda{}, + 'http://falsehost/arf' => lambda{}, + 'http://falsehost/qux' => lambda{} + }) + opt = {:map => true, :Port => 9241, :Host => 'localhost'} + Rack::Handler::Mongrel.run(map, opt) { |server| + server.should.be.kind_of Mongrel::HttpServer + server.classifier.uris.should.include '/' + server.classifier.handler_map['/'].size.should.equal 2 + server.classifier.uris.should.include '/foo' + server.classifier.handler_map['/foo'].size.should.equal 1 + server.classifier.uris.should.include '/bar' + server.classifier.handler_map['/bar'].size.should.equal 2 + server.classifier.uris.should.not.include '/qux' + server.classifier.uris.should.not.include '/arf' + server.classifier.uris.size.should.equal 3 + block_ran = true + } + } + sleep 1 + block_ran.should.be.true + end + + should "stream #each part of the response" do + body = '' + begin + Timeout.timeout(1) do + Net::HTTP.start(@host, @port) do |http| + get = Net::HTTP::Get.new('/stream') + http.request(get) do |response| + response.read_body { |part| body << part } + end + end + end + rescue Timeout::Error + end + body.should.not.be.empty + end + + @acc.raise Mongrel::StopServer +end + +rescue LoadError + warn "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again." +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_multipart.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_multipart.rb new file mode 100644 index 0000000..99c4aee --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_multipart.rb @@ -0,0 +1,298 @@ +require 'rack/utils' +require 'rack/mock' + +describe Rack::Multipart do + def multipart_fixture(name) + file = multipart_file(name) + data = File.open(file, 'rb') { |io| io.read } + + type = "multipart/form-data; boundary=AaB03x" + length = data.respond_to?(:bytesize) ? data.bytesize : data.size + + { "CONTENT_TYPE" => type, + "CONTENT_LENGTH" => length.to_s, + :input => StringIO.new(data) } + end + + def multipart_file(name) + File.join(File.dirname(__FILE__), "multipart", name.to_s) + end + + should "return nil if content type is not multipart" do + env = Rack::MockRequest.env_for("/", + "CONTENT_TYPE" => 'application/x-www-form-urlencoded') + Rack::Multipart.parse_multipart(env).should.equal nil + end + + should "parse multipart content when content type present but filename is not" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename)) + params = Rack::Multipart.parse_multipart(env) + params["text"].should.equal "contents" + end + + should "raise RangeError if the key space is exhausted" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename)) + + old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1 + begin + lambda { Rack::Multipart.parse_multipart(env) }.should.raise(RangeError) + ensure + Rack::Utils.key_space_limit = old + end + end + + should "parse multipart form webkit style" do + env = Rack::MockRequest.env_for '/', multipart_fixture(:webkit) + env['CONTENT_TYPE'] = "multipart/form-data; boundary=----WebKitFormBoundaryWLHCs9qmcJJoyjKR" + params = Rack::Multipart.parse_multipart(env) + params['profile']['bio'].should.include 'hello' + end + + should "parse multipart upload with text file" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:text)) + params = Rack::Multipart.parse_multipart(env) + params["submit-name"].should.equal "Larry" + params["submit-name-with-content"].should.equal "Berry" + params["files"][:type].should.equal "text/plain" + params["files"][:filename].should.equal "file1.txt" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; filename=\"file1.txt\"\r\n" + + "Content-Type: text/plain\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "parse multipart upload with nested parameters" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:nested)) + params = Rack::Multipart.parse_multipart(env) + params["foo"]["submit-name"].should.equal "Larry" + params["foo"]["files"][:type].should.equal "text/plain" + params["foo"]["files"][:filename].should.equal "file1.txt" + params["foo"]["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"foo[files]\"; filename=\"file1.txt\"\r\n" + + "Content-Type: text/plain\r\n" + params["foo"]["files"][:name].should.equal "foo[files]" + params["foo"]["files"][:tempfile].read.should.equal "contents" + end + + should "parse multipart upload with binary file" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:binary)) + params = Rack::Multipart.parse_multipart(env) + params["submit-name"].should.equal "Larry" + params["files"][:type].should.equal "image/png" + params["files"][:filename].should.equal "rack-logo.png" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; filename=\"rack-logo.png\"\r\n" + + "Content-Type: image/png\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.length.should.equal 26473 + end + + should "parse multipart upload with empty file" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:empty)) + params = Rack::Multipart.parse_multipart(env) + params["submit-name"].should.equal "Larry" + params["files"][:type].should.equal "text/plain" + params["files"][:filename].should.equal "file1.txt" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; filename=\"file1.txt\"\r\n" + + "Content-Type: text/plain\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "" + end + + should "parse multipart upload with filename with semicolons" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:semicolon)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "text/plain" + params["files"][:filename].should.equal "fi;le1.txt" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; filename=\"fi;le1.txt\"\r\n" + + "Content-Type: text/plain\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "not include file params if no file was selected" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:none)) + params = Rack::Multipart.parse_multipart(env) + params["submit-name"].should.equal "Larry" + params["files"].should.equal nil + params.keys.should.not.include "files" + end + + should "parse multipart/mixed" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:mixed_files)) + params = Rack::Utils::Multipart.parse_multipart(env) + params["foo"].should.equal "bar" + params["files"].should.be.instance_of String + params["files"].size.should.equal 252 + end + + should "parse IE multipart upload and clean up filename" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:ie)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "text/plain" + params["files"][:filename].should.equal "file1.txt" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; " + + 'filename="C:\Documents and Settings\Administrator\Desktop\file1.txt"' + + "\r\nContent-Type: text/plain\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "parse filename and modification param" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_and_modification_param)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "image/jpeg" + params["files"][:filename].should.equal "genome.jpeg" + params["files"][:head].should.equal "Content-Type: image/jpeg\r\n" + + "Content-Disposition: attachment; " + + "name=\"files\"; " + + "filename=genome.jpeg; " + + "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" + + "Content-Description: a complete map of the human genome\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "parse filename with escaped quotes" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "application/octet-stream" + params["files"][:filename].should.equal "escape \"quotes" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; " + + "filename=\"escape \\\"quotes\"\r\n" + + "Content-Type: application/octet-stream\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "parse filename with percent escaped quotes" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_percent_escaped_quotes)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "application/octet-stream" + params["files"][:filename].should.equal "escape \"quotes" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; " + + "filename=\"escape %22quotes\"\r\n" + + "Content-Type: application/octet-stream\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "parse filename with unescaped quotes" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_quotes)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "application/octet-stream" + params["files"][:filename].should.equal "escape \"quotes" + params["files"][:head].should.equal "Content-Disposition: form-data; " + + "name=\"files\"; " + + "filename=\"escape \"quotes\"\r\n" + + "Content-Type: application/octet-stream\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + should "parse filename with escaped quotes and modification param" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes_and_modification_param)) + params = Rack::Multipart.parse_multipart(env) + params["files"][:type].should.equal "image/jpeg" + params["files"][:filename].should.equal "\"human\" genome.jpeg" + params["files"][:head].should.equal "Content-Type: image/jpeg\r\n" + + "Content-Disposition: attachment; " + + "name=\"files\"; " + + "filename=\"\"human\" genome.jpeg\"; " + + "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" + + "Content-Description: a complete map of the human genome\r\n" + params["files"][:name].should.equal "files" + params["files"][:tempfile].read.should.equal "contents" + end + + it "rewinds input after parsing upload" do + options = multipart_fixture(:text) + input = options[:input] + env = Rack::MockRequest.env_for("/", options) + params = Rack::Multipart.parse_multipart(env) + params["submit-name"].should.equal "Larry" + params["files"][:filename].should.equal "file1.txt" + input.read.length.should.equal 307 + end + + it "builds multipart body" do + files = Rack::Multipart::UploadedFile.new(multipart_file("file1.txt")) + data = Rack::Multipart.build_multipart("submit-name" => "Larry", "files" => files) + + options = { + "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", + "CONTENT_LENGTH" => data.length.to_s, + :input => StringIO.new(data) + } + env = Rack::MockRequest.env_for("/", options) + params = Rack::Multipart.parse_multipart(env) + params["submit-name"].should.equal "Larry" + params["files"][:filename].should.equal "file1.txt" + params["files"][:tempfile].read.should.equal "contents" + end + + it "builds nested multipart body" do + files = Rack::Multipart::UploadedFile.new(multipart_file("file1.txt")) + data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => files}]) + + options = { + "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x", + "CONTENT_LENGTH" => data.length.to_s, + :input => StringIO.new(data) + } + env = Rack::MockRequest.env_for("/", options) + params = Rack::Multipart.parse_multipart(env) + params["people"][0]["submit-name"].should.equal "Larry" + params["people"][0]["files"][:filename].should.equal "file1.txt" + params["people"][0]["files"][:tempfile].read.should.equal "contents" + end + + it "can parse fields that end at the end of the buffer" do + input = File.read(multipart_file("bad_robots")) + + req = Rack::Request.new Rack::MockRequest.env_for("/", + "CONTENT_TYPE" => "multipart/form-data, boundary=1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon", + "CONTENT_LENGTH" => input.size, + :input => input) + + req.POST['file.path'].should.equal "/var/tmp/uploads/4/0001728414" + req.POST['addresses'].should.not.equal nil + end + + it "builds complete params with the chunk size of 16384 slicing exactly on boundary" do + data = File.open(multipart_file("fail_16384_nofile")) { |f| f.read }.gsub(/\n/, "\r\n") + options = { + "CONTENT_TYPE" => "multipart/form-data; boundary=----WebKitFormBoundaryWsY0GnpbI5U7ztzo", + "CONTENT_LENGTH" => data.length.to_s, + :input => StringIO.new(data) + } + env = Rack::MockRequest.env_for("/", options) + params = Rack::Multipart.parse_multipart(env) + + params.should.not.equal nil + params.keys.should.include "AAAAAAAAAAAAAAAAAAA" + params["AAAAAAAAAAAAAAAAAAA"].keys.should.include "PLAPLAPLA_MEMMEMMEMM_ATTRATTRER" + params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"].keys.should.include "new" + params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"].keys.should.include "-2" + params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"].keys.should.include "ba_unit_id" + params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"]["ba_unit_id"].should.equal "1017" + end + + should "return nil if no UploadedFiles were used" do + data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}]) + data.should.equal nil + end + + should "raise ArgumentError if params is not a Hash" do + lambda { Rack::Multipart.build_multipart("foo=bar") }. + should.raise(ArgumentError). + message.should.equal "value must be a Hash" + end + +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_nulllogger.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_nulllogger.rb new file mode 100644 index 0000000..7c1968e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_nulllogger.rb @@ -0,0 +1,12 @@ +require 'rack/nulllogger' + +describe Rack::NullLogger do + should "act as a noop logger" do + app = lambda { |env| + env['rack.logger'].warn "b00m" + [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] + } + logger = Rack::NullLogger.new(app) + lambda{ logger.call({}) }.should.not.raise + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_recursive.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_recursive.rb new file mode 100644 index 0000000..592b263 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_recursive.rb @@ -0,0 +1,69 @@ +require 'rack/recursive' +require 'rack/mock' + +describe Rack::Recursive do + @app1 = lambda { |env| + res = Rack::Response.new + res["X-Path-Info"] = env["PATH_INFO"] + res["X-Query-String"] = env["QUERY_STRING"] + res.finish do |inner_res| + inner_res.write "App1" + end + } + + @app2 = lambda { |env| + Rack::Response.new.finish do |res| + res.write "App2" + _, _, body = env['rack.recursive.include'].call(env, "/app1") + body.each { |b| + res.write b + } + end + } + + @app3 = lambda { |env| + raise Rack::ForwardRequest.new("/app1") + } + + @app4 = lambda { |env| + raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh") + } + + should "allow for subrequests" do + res = Rack::MockRequest.new(Rack::Recursive.new( + Rack::URLMap.new("/app1" => @app1, + "/app2" => @app2))). + get("/app2") + + res.should.be.ok + res.body.should.equal "App2App1" + end + + should "raise error on requests not below the app" do + app = Rack::URLMap.new("/app1" => @app1, + "/app" => Rack::Recursive.new( + Rack::URLMap.new("/1" => @app1, + "/2" => @app2))) + + lambda { + Rack::MockRequest.new(app).get("/app/2") + }.should.raise(ArgumentError). + message.should =~ /can only include below/ + end + + should "support forwarding" do + app = Rack::Recursive.new(Rack::URLMap.new("/app1" => @app1, + "/app3" => @app3, + "/app4" => @app4)) + + res = Rack::MockRequest.new(app).get("/app3") + res.should.be.ok + res.body.should.equal "App1" + + res = Rack::MockRequest.new(app).get("/app4") + res.should.be.ok + res.body.should.equal "App1" + res["X-Path-Info"].should.equal "/quux" + res["X-Query-String"].should.equal "meh" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_request.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_request.rb new file mode 100644 index 0000000..9343932 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_request.rb @@ -0,0 +1,852 @@ +require 'stringio' +require 'cgi' +require 'rack/request' +require 'rack/mock' + +describe Rack::Request do + should "wrap the rack variables" do + req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/")) + + req.body.should.respond_to? :gets + req.scheme.should.equal "http" + req.request_method.should.equal "GET" + + req.should.be.get + req.should.not.be.post + req.should.not.be.put + req.should.not.be.delete + req.should.not.be.head + req.should.not.be.patch + + req.script_name.should.equal "" + req.path_info.should.equal "/" + req.query_string.should.equal "" + + req.host.should.equal "example.com" + req.port.should.equal 8080 + + req.content_length.should.equal "0" + req.content_type.should.be.nil + end + + should "figure out the correct host" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org") + req.host.should.equal "www2.example.org" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292") + req.host.should.equal "example.org" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292") + req.host.should.equal "example.org" + + env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292") + env.delete("SERVER_NAME") + req = Rack::Request.new(env) + req.host.should.equal "192.168.1.1" + + env = Rack::MockRequest.env_for("/") + env.delete("SERVER_NAME") + req = Rack::Request.new(env) + req.host.should.equal "" + end + + should "figure out the correct port" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org") + req.port.should.equal 80 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org:81") + req.port.should.equal 81 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292") + req.port.should.equal 9292 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292") + req.port.should.equal 9292 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org") + req.port.should.equal 80 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_SSL" => "on") + req.port.should.equal 443 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PROTO" => "https") + req.port.should.equal 443 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PORT" => "9393") + req.port.should.equal 9393 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9393", "SERVER_PORT" => "80") + req.port.should.equal 9393 + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393") + req.port.should.equal 80 + end + + should "figure out the correct host with port" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org") + req.host_with_port.should.equal "www2.example.org" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81") + req.host_with_port.should.equal "localhost:81" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292") + req.host_with_port.should.equal "example.org:9292" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292") + req.host_with_port.should.equal "example.org:9292" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393") + req.host_with_port.should.equal "example.org" + end + + should "parse the query string" do + req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla")) + req.query_string.should.equal "foo=bar&quux=bla" + req.GET.should.equal "foo" => "bar", "quux" => "bla" + req.POST.should.be.empty + req.params.should.equal "foo" => "bar", "quux" => "bla" + end + + should "limit the keys from the GET query string" do + env = Rack::MockRequest.env_for("/?foo=bar") + + old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1 + begin + req = Rack::Request.new(env) + lambda { req.GET }.should.raise(RangeError) + ensure + Rack::Utils.key_space_limit = old + end + end + + should "not unify GET and POST when calling params" do + mr = Rack::MockRequest.env_for("/?foo=quux", + "REQUEST_METHOD" => 'POST', + :input => "foo=bar&quux=bla" + ) + req = Rack::Request.new mr + + req.params + + req.GET.should.equal "foo" => "quux" + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.params.should.equal req.GET.merge(req.POST) + end + + should "raise if rack.input is missing" do + req = Rack::Request.new({}) + lambda { req.POST }.should.raise(RuntimeError) + end + + should "parse POST data when method is POST and no Content-Type given" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/?foo=quux", + "REQUEST_METHOD" => 'POST', + :input => "foo=bar&quux=bla") + req.content_type.should.be.nil + req.media_type.should.be.nil + req.query_string.should.equal "foo=quux" + req.GET.should.equal "foo" => "quux" + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.params.should.equal "foo" => "bar", "quux" => "bla" + end + + should "limit the keys from the POST form data" do + env = Rack::MockRequest.env_for("", + "REQUEST_METHOD" => 'POST', + :input => "foo=bar&quux=bla") + + old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1 + begin + req = Rack::Request.new(env) + lambda { req.POST }.should.raise(RangeError) + ensure + Rack::Utils.key_space_limit = old + end + end + + should "parse POST data with explicit content type regardless of method" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", + "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar', + :input => "foo=bar&quux=bla") + req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar' + req.media_type.should.equal 'application/x-www-form-urlencoded' + req.media_type_params['foo'].should.equal 'bar' + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.params.should.equal "foo" => "bar", "quux" => "bla" + end + + should "not parse POST data when media type is not form-data" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/?foo=quux", + "REQUEST_METHOD" => 'POST', + "CONTENT_TYPE" => 'text/plain;charset=utf-8', + :input => "foo=bar&quux=bla") + req.content_type.should.equal 'text/plain;charset=utf-8' + req.media_type.should.equal 'text/plain' + req.media_type_params['charset'].should.equal 'utf-8' + req.POST.should.be.empty + req.params.should.equal "foo" => "quux" + req.body.read.should.equal "foo=bar&quux=bla" + end + + should "parse POST data on PUT when media type is form-data" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/?foo=quux", + "REQUEST_METHOD" => 'PUT', + "CONTENT_TYPE" => 'application/x-www-form-urlencoded', + :input => "foo=bar&quux=bla") + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.body.read.should.equal "foo=bar&quux=bla" + end + + should "rewind input after parsing POST data" do + input = StringIO.new("foo=bar&quux=bla") + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", + "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar', + :input => input) + req.params.should.equal "foo" => "bar", "quux" => "bla" + input.read.should.equal "foo=bar&quux=bla" + end + + should "clean up Safari's ajax POST body" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", + 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0") + req.POST.should.equal "foo" => "bar", "quux" => "bla" + end + + should "get value by key from params with #[]" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("?foo=quux") + req['foo'].should.equal 'quux' + req[:foo].should.equal 'quux' + end + + should "set value to key on params with #[]=" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("?foo=duh") + req['foo'].should.equal 'duh' + req[:foo].should.equal 'duh' + req.params.should.equal 'foo' => 'duh' + + req['foo'] = 'bar' + req.params.should.equal 'foo' => 'bar' + req['foo'].should.equal 'bar' + req[:foo].should.equal 'bar' + + req[:foo] = 'jaz' + req.params.should.equal 'foo' => 'jaz' + req['foo'].should.equal 'jaz' + req[:foo].should.equal 'jaz' + end + + should "return values for the keys in the order given from values_at" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful") + req.values_at('foo').should.equal ['baz'] + req.values_at('foo', 'wun').should.equal ['baz', 'der'] + req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der'] + end + + should "extract referrer correctly" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path") + req.referer.should.equal "/some/path" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/") + req.referer.should.equal nil + end + + should "extract user agent correctly" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)") + req.user_agent.should.equal "Mozilla/4.0 (compatible)" + + req = Rack::Request.new \ + Rack::MockRequest.env_for("/") + req.user_agent.should.equal nil + end + + should "treat missing content type as nil" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/") + req.content_type.should.equal nil + end + + should "treat empty content type as nil" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "") + req.content_type.should.equal nil + end + + should "return nil media type for empty content type" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "") + req.media_type.should.equal nil + end + + should "cache, but invalidates the cache" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/?foo=quux", + "CONTENT_TYPE" => "application/x-www-form-urlencoded", + :input => "foo=bar&quux=bla") + req.GET.should.equal "foo" => "quux" + req.GET.should.equal "foo" => "quux" + req.env["QUERY_STRING"] = "bla=foo" + req.GET.should.equal "bla" => "foo" + req.GET.should.equal "bla" => "foo" + + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.env["rack.input"] = StringIO.new("foo=bla&quux=bar") + req.POST.should.equal "foo" => "bla", "quux" => "bar" + req.POST.should.equal "foo" => "bla", "quux" => "bar" + end + + should "figure out if called via XHR" do + req = Rack::Request.new(Rack::MockRequest.env_for("")) + req.should.not.be.xhr + + req = Rack::Request.new \ + Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest") + req.should.be.xhr + end + + should "ssl detection" do + request = Rack::Request.new(Rack::MockRequest.env_for("/")) + request.scheme.should.equal "http" + request.should.not.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTPS' => 'on')) + request.scheme.should.equal "https" + request.should.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https')) + request.scheme.should.equal "https" + request.should.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080')) + request.scheme.should.equal "http" + request.should.not.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on')) + request.scheme.should.equal "https" + request.should.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on')) + request.scheme.should.equal "https" + request.should.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https')) + request.scheme.should.equal "https" + request.should.be.ssl? + + request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http')) + request.scheme.should.equal "https" + request.should.be.ssl + end + + should "parse cookies" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m") + req.cookies.should.equal "foo" => "bar", "quux" => "h&m" + req.cookies.should.equal "foo" => "bar", "quux" => "h&m" + req.env.delete("HTTP_COOKIE") + req.cookies.should.equal({}) + end + + should "always return the same hash object" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m") + hash = req.cookies + req.env.delete("HTTP_COOKIE") + req.cookies.should.equal(hash) + end + + should "raise any errors on every request" do + req = Rack::Request.new Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%") + 2.times { proc { req.cookies }.should.raise(ArgumentError) } + end + + should "parse cookies according to RFC 2109" do + req = Rack::Request.new \ + Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car') + req.cookies.should.equal 'foo' => 'bar' + end + + should 'parse cookies with quotes' do + req = Rack::Request.new Rack::MockRequest.env_for('', { + 'HTTP_COOKIE' => '$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"' + }) + req.cookies.should.equal({ + '$Version' => '"1"', + 'Customer' => '"WILE_E_COYOTE"', + '$Path' => '"/acme"', + 'Part_Number' => '"Rocket_Launcher_0001"', + }) + end + + should "provide setters" do + req = Rack::Request.new(e=Rack::MockRequest.env_for("")) + req.script_name.should.equal "" + req.script_name = "/foo" + req.script_name.should.equal "/foo" + e["SCRIPT_NAME"].should.equal "/foo" + + req.path_info.should.equal "/" + req.path_info = "/foo" + req.path_info.should.equal "/foo" + e["PATH_INFO"].should.equal "/foo" + end + + should "provide the original env" do + req = Rack::Request.new(e = Rack::MockRequest.env_for("")) + req.env.should == e + end + + should "restore the base URL" do + Rack::Request.new(Rack::MockRequest.env_for("")).base_url. + should.equal "http://example.org" + Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url. + should.equal "http://example.org" + end + + should "restore the URL" do + Rack::Request.new(Rack::MockRequest.env_for("")).url. + should.equal "http://example.org/" + Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url. + should.equal "http://example.org/foo/" + Rack::Request.new(Rack::MockRequest.env_for("/foo")).url. + should.equal "http://example.org/foo" + Rack::Request.new(Rack::MockRequest.env_for("?foo")).url. + should.equal "http://example.org/?foo" + Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url. + should.equal "http://example.org:8080/" + Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url. + should.equal "https://example.org/" + + Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url. + should.equal "https://example.com:8080/foo?foo" + end + + should "restore the full path" do + Rack::Request.new(Rack::MockRequest.env_for("")).fullpath. + should.equal "/" + Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath. + should.equal "/foo/" + Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath. + should.equal "/foo" + Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath. + should.equal "/?foo" + Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath. + should.equal "/" + Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath. + should.equal "/" + + Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath. + should.equal "/foo?foo" + end + + should "handle multiple media type parameters" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/", + "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam') + req.should.not.be.form_data + req.media_type_params.should.include 'foo' + req.media_type_params['foo'].should.equal 'BAR' + req.media_type_params.should.include 'baz' + req.media_type_params['baz'].should.equal 'bizzle dizzle' + req.media_type_params.should.not.include 'BLING' + req.media_type_params.should.include 'bling' + req.media_type_params['bling'].should.equal 'bam' + end + + should "parse with junk before boundry" do + # Adapted from RFC 1867. + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + req.POST.should.include "fileupload" + req.POST.should.include "reply" + + req.should.be.form_data + req.content_length.should.equal input.size + req.media_type.should.equal 'multipart/form-data' + req.media_type_params.should.include 'boundary' + req.media_type_params['boundary'].should.equal 'AaB03x' + + req.POST["reply"].should.equal "yes" + + f = req.POST["fileupload"] + f.should.be.kind_of Hash + f[:type].should.equal "image/jpeg" + f[:filename].should.equal "dj.jpg" + f.should.include :tempfile + f[:tempfile].size.should.equal 76 + end + + should "not infinite loop with a malformed HTTP request" do + # Adapted from RFC 1867. + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + lambda{req.POST}.should.raise(EOFError) + end + + + should "parse multipart form data" do + # Adapted from RFC 1867. + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + req.POST.should.include "fileupload" + req.POST.should.include "reply" + + req.should.be.form_data + req.content_length.should.equal input.size + req.media_type.should.equal 'multipart/form-data' + req.media_type_params.should.include 'boundary' + req.media_type_params['boundary'].should.equal 'AaB03x' + + req.POST["reply"].should.equal "yes" + + f = req.POST["fileupload"] + f.should.be.kind_of Hash + f[:type].should.equal "image/jpeg" + f[:filename].should.equal "dj.jpg" + f.should.include :tempfile + f[:tempfile].size.should.equal 76 + end + + should "parse big multipart form data" do + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + req.POST["huge"][:tempfile].size.should.equal 32768 + req.POST["mean"][:tempfile].size.should.equal 10 + req.POST["mean"][:tempfile].read.should.equal "--AaB03xha" + end + + should "detect invalid multipart form data" do + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + lambda { req.POST }.should.raise(EOFError) + + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + lambda { req.POST }.should.raise(EOFError) + + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + lambda { req.POST }.should.raise(EOFError) + end + + should "correctly parse the part name from Content-Id header" do + input = <\r +Content-Transfer-Encoding: 7bit\r +\r +foo\r +--AaB03x--\r +EOF + req = Rack::Request.new Rack::MockRequest.env_for("/", + "CONTENT_TYPE" => "multipart/related, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + req.params.keys.should.equal [""] + end + + should "not try to interpret binary as utf8" do + if /regexp/.respond_to?(:kcode) # < 1.9 + begin + original_kcode = $KCODE + $KCODE='UTF8' + + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + lambda{req.POST}.should.not.raise(EOFError) + req.POST["fileupload"][:tempfile].size.should.equal 4 + ensure + $KCODE = original_kcode + end + else # >= 1.9 + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => input) + + lambda{req.POST}.should.not.raise(EOFError) + req.POST["fileupload"][:tempfile].size.should.equal 4 + end + end + + should "work around buggy 1.8.* Tempfile equality" do + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size, + :input => rack_input) + + lambda{ req.POST }.should.not.raise + lambda{ req.POST }.should.not.raise("input re-processed!") + end + + should "conform to the Rack spec" do + app = lambda { |env| + content = Rack::Request.new(env).POST["file"].inspect + size = content.respond_to?(:bytesize) ? content.bytesize : content.size + [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]] + } + + input = < "multipart/form-data, boundary=AaB03x", + "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input) + + res.should.be.ok + end + + should "parse Accept-Encoding correctly" do + parser = lambda do |x| + Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding + end + + parser.call(nil).should.equal([]) + + parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]]) + parser.call("").should.equal([]) + parser.call("*").should.equal([["*", 1.0]]) + parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]]) + parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ]) + + lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError) + end + + should 'provide ip information' do + app = lambda { |env| + request = Rack::Request.new(env) + response = Rack::Response.new + response.write request.ip + response.finish + } + + mock = Rack::MockRequest.new(Rack::Lint.new(app)) + res = mock.get '/', 'REMOTE_ADDR' => '123.123.123.123' + res.body.should.equal '123.123.123.123' + + res = mock.get '/', + 'REMOTE_ADDR' => '123.123.123.123', + 'HTTP_X_FORWARDED_FOR' => '234.234.234.234' + + res.body.should.equal '234.234.234.234' + + res = mock.get '/', + 'REMOTE_ADDR' => '123.123.123.123', + 'HTTP_X_FORWARDED_FOR' => '234.234.234.234,212.212.212.212' + + res.body.should.equal '234.234.234.234' + + res = mock.get '/', + 'REMOTE_ADDR' => '123.123.123.123', + 'HTTP_X_FORWARDED_FOR' => 'unknown,234.234.234.234,212.212.212.212' + + res.body.should.equal '234.234.234.234' + end + + class MyRequest < Rack::Request + def params + {:foo => "bar"} + end + end + + should "allow subclass request to be instantiated after parent request" do + env = Rack::MockRequest.env_for("/?foo=bar") + + req1 = Rack::Request.new(env) + req1.GET.should.equal "foo" => "bar" + req1.params.should.equal "foo" => "bar" + + req2 = MyRequest.new(env) + req2.GET.should.equal "foo" => "bar" + req2.params.should.equal :foo => "bar" + end + + should "allow parent request to be instantiated after subclass request" do + env = Rack::MockRequest.env_for("/?foo=bar") + + req1 = MyRequest.new(env) + req1.GET.should.equal "foo" => "bar" + req1.params.should.equal :foo => "bar" + + req2 = Rack::Request.new(env) + req2.GET.should.equal "foo" => "bar" + req2.params.should.equal "foo" => "bar" + end + + (0x20...0x7E).collect { |a| + b = a.chr + c = CGI.escape(b) + should "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do + url = "/?foo=#{c}bar#{c}" + env = Rack::MockRequest.env_for(url) + req2 = Rack::Request.new(env) + req2.GET.should.equal "foo" => "#{b}bar#{b}" + req2.params.should.equal "foo" => "#{b}bar#{b}" + end + } +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_response.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_response.rb new file mode 100644 index 0000000..c92fa5b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_response.rb @@ -0,0 +1,253 @@ +require 'set' +require 'rack/response' +require 'stringio' + +describe Rack::Response do + should "have sensible default values" do + response = Rack::Response.new + status, header, body = response.finish + status.should.equal 200 + header.should.equal "Content-Type" => "text/html" + body.each { |part| + part.should.equal "" + } + + response = Rack::Response.new + status, header, body = *response + status.should.equal 200 + header.should.equal "Content-Type" => "text/html" + body.each { |part| + part.should.equal "" + } + end + + it "can be written to" do + response = Rack::Response.new + + _, _, body = response.finish do + response.write "foo" + response.write "bar" + response.write "baz" + end + + parts = [] + body.each { |part| parts << part } + + parts.should.equal ["foo", "bar", "baz"] + end + + it "can set and read headers" do + response = Rack::Response.new + response["Content-Type"].should.equal "text/html" + response["Content-Type"] = "text/plain" + response["Content-Type"].should.equal "text/plain" + end + + it "can override the initial Content-Type with a different case" do + response = Rack::Response.new("", 200, "content-type" => "text/plain") + response["Content-Type"].should.equal "text/plain" + end + + it "can set cookies" do + response = Rack::Response.new + + response.set_cookie "foo", "bar" + response["Set-Cookie"].should.equal "foo=bar" + response.set_cookie "foo2", "bar2" + response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2"].join("\n") + response.set_cookie "foo3", "bar3" + response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2", "foo3=bar3"].join("\n") + end + + it "can set cookies with the same name for multiple domains" do + response = Rack::Response.new + response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"} + response.set_cookie "foo", {:value => "bar", :domain => ".example.com"} + response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n") + end + + it "formats the Cookie expiration date accordingly to RFC 2109" do + response = Rack::Response.new + + response.set_cookie "foo", {:value => "bar", :expires => Time.now+10} + response["Set-Cookie"].should.match( + /expires=..., \d\d-...-\d\d\d\d \d\d:\d\d:\d\d .../) + end + + it "can set secure cookies" do + response = Rack::Response.new + response.set_cookie "foo", {:value => "bar", :secure => true} + response["Set-Cookie"].should.equal "foo=bar; secure" + end + + it "can set http only cookies" do + response = Rack::Response.new + response.set_cookie "foo", {:value => "bar", :httponly => true} + response["Set-Cookie"].should.equal "foo=bar; HttpOnly" + end + + it "can delete cookies" do + response = Rack::Response.new + response.set_cookie "foo", "bar" + response.set_cookie "foo2", "bar2" + response.delete_cookie "foo" + response["Set-Cookie"].should.equal [ + "foo2=bar2", + "foo=; expires=Thu, 01-Jan-1970 00:00:00 GMT" + ].join("\n") + end + + it "can delete cookies with the same name from multiple domains" do + response = Rack::Response.new + response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"} + response.set_cookie "foo", {:value => "bar", :domain => ".example.com"} + response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n") + response.delete_cookie "foo", :domain => ".example.com" + response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=; domain=.example.com; expires=Thu, 01-Jan-1970 00:00:00 GMT"].join("\n") + response.delete_cookie "foo", :domain => "sample.example.com" + response["Set-Cookie"].should.equal ["foo=; domain=.example.com; expires=Thu, 01-Jan-1970 00:00:00 GMT", + "foo=; domain=sample.example.com; expires=Thu, 01-Jan-1970 00:00:00 GMT"].join("\n") + end + + it "can do redirects" do + response = Rack::Response.new + response.redirect "/foo" + status, header, body = response.finish + + status.should.equal 302 + header["Location"].should.equal "/foo" + + response = Rack::Response.new + response.redirect "/foo", 307 + status, header, body = response.finish + + status.should.equal 307 + end + + it "has a useful constructor" do + r = Rack::Response.new("foo") + status, header, body = r.finish + str = ""; body.each { |part| str << part } + str.should.equal "foo" + + r = Rack::Response.new(["foo", "bar"]) + status, header, body = r.finish + str = ""; body.each { |part| str << part } + str.should.equal "foobar" + + r = Rack::Response.new(["foo", "bar"].to_set) + r.write "foo" + status, header, body = r.finish + str = ""; body.each { |part| str << part } + str.should.equal "foobarfoo" + + r = Rack::Response.new([], 500) + r.status.should.equal 500 + + r = Rack::Response.new([], "200 OK") + r.status.should.equal 200 + end + + it "has a constructor that can take a block" do + r = Rack::Response.new { |res| + res.status = 404 + res.write "foo" + } + status, _, body = r.finish + str = ""; body.each { |part| str << part } + str.should.equal "foo" + status.should.equal 404 + end + + it "doesn't return invalid responses" do + r = Rack::Response.new(["foo", "bar"], 204) + _, header, body = r.finish + str = ""; body.each { |part| str << part } + str.should.be.empty + header["Content-Type"].should.equal nil + header['Content-Length'].should.equal nil + + lambda { + Rack::Response.new(Object.new) + }.should.raise(TypeError). + message.should =~ /stringable or iterable required/ + end + + it "knows if it's empty" do + r = Rack::Response.new + r.should.be.empty + r.write "foo" + r.should.not.be.empty + + r = Rack::Response.new + r.should.be.empty + r.finish + r.should.be.empty + + r = Rack::Response.new + r.should.be.empty + r.finish { } + r.should.not.be.empty + end + + should "provide access to the HTTP status" do + res = Rack::Response.new + res.status = 200 + res.should.be.successful + res.should.be.ok + + res.status = 404 + res.should.not.be.successful + res.should.be.client_error + res.should.be.not_found + + res.status = 501 + res.should.not.be.successful + res.should.be.server_error + + res.status = 307 + res.should.be.redirect + end + + should "provide access to the HTTP headers" do + res = Rack::Response.new + res["Content-Type"] = "text/yaml" + + res.should.include "Content-Type" + res.headers["Content-Type"].should.equal "text/yaml" + res["Content-Type"].should.equal "text/yaml" + res.content_type.should.equal "text/yaml" + res.content_length.should.be.nil + res.location.should.be.nil + end + + it "does not add or change Content-Length when #finish()ing" do + res = Rack::Response.new + res.status = 200 + res.finish + res.headers["Content-Length"].should.be.nil + + res = Rack::Response.new + res.status = 200 + res.headers["Content-Length"] = "10" + res.finish + res.headers["Content-Length"].should.equal "10" + end + + it "updates Content-Length when body appended to using #write" do + res = Rack::Response.new + res.status = 200 + res.headers["Content-Length"].should.be.nil + res.write "Hi" + res.headers["Content-Length"].should.equal "2" + res.write " there" + res.headers["Content-Length"].should.equal "8" + end + + it "calls close on #body" do + res = Rack::Response.new + res.body = StringIO.new + res.close + res.body.should.be.closed + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_rewindable_input.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_rewindable_input.rb new file mode 100644 index 0000000..025d830 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_rewindable_input.rb @@ -0,0 +1,118 @@ +require 'stringio' +require 'rack/rewindable_input' + +shared "a rewindable IO object" do + before do + @rio = Rack::RewindableInput.new(@io) + end + + should "be able to handle to read()" do + @rio.read.should.equal "hello world" + end + + should "be able to handle to read(nil)" do + @rio.read(nil).should.equal "hello world" + end + + should "be able to handle to read(length)" do + @rio.read(1).should.equal "h" + end + + should "be able to handle to read(length, buffer)" do + buffer = "" + result = @rio.read(1, buffer) + result.should.equal "h" + result.object_id.should.equal buffer.object_id + end + + should "be able to handle to read(nil, buffer)" do + buffer = "" + result = @rio.read(nil, buffer) + result.should.equal "hello world" + result.object_id.should.equal buffer.object_id + end + + should "rewind to the beginning when #rewind is called" do + @rio.read(1) + @rio.rewind + @rio.read.should.equal "hello world" + end + + should "be able to handle gets" do + @rio.gets.should == "hello world" + end + + should "be able to handle each" do + array = [] + @rio.each do |data| + array << data + end + array.should.equal(["hello world"]) + end + + should "not buffer into a Tempfile if no data has been read yet" do + @rio.instance_variable_get(:@rewindable_io).should.be.nil + end + + should "buffer into a Tempfile when data has been consumed for the first time" do + @rio.read(1) + tempfile = @rio.instance_variable_get(:@rewindable_io) + tempfile.should.not.be.nil + @rio.read(1) + tempfile2 = @rio.instance_variable_get(:@rewindable_io) + tempfile2.path.should == tempfile.path + end + + should "close the underlying tempfile upon calling #close" do + @rio.read(1) + tempfile = @rio.instance_variable_get(:@rewindable_io) + @rio.close + tempfile.should.be.closed + end + + should "be possible to call #close when no data has been buffered yet" do + lambda{ @rio.close }.should.not.raise + end + + should "be possible to call #close multiple times" do + lambda{ + @rio.close + @rio.close + }.should.not.raise + end + + @rio.close + @rio = nil +end + +describe Rack::RewindableInput do + describe "given an IO object that is already rewindable" do + before do + @io = StringIO.new("hello world") + end + + behaves_like "a rewindable IO object" + end + + describe "given an IO object that is not rewindable" do + before do + @io = StringIO.new("hello world") + @io.instance_eval do + undef :rewind + end + end + + behaves_like "a rewindable IO object" + end + + describe "given an IO object whose rewind method raises Errno::ESPIPE" do + before do + @io = StringIO.new("hello world") + def @io.rewind + raise Errno::ESPIPE, "You can't rewind this!" + end + end + + behaves_like "a rewindable IO object" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_runtime.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_runtime.rb new file mode 100644 index 0000000..547a32e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_runtime.rb @@ -0,0 +1,39 @@ +require 'rack/runtime' + +describe Rack::Runtime do + it "sets X-Runtime is none is set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] } + response = Rack::Runtime.new(app).call({}) + response[1]['X-Runtime'].should =~ /[\d\.]+/ + end + + it "doesn't set the X-Runtime if it is already set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] } + response = Rack::Runtime.new(app).call({}) + response[1]['X-Runtime'].should == "foobar" + end + + should "allow a suffix to be set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] } + response = Rack::Runtime.new(app, "Test").call({}) + response[1]['X-Runtime-Test'].should =~ /[\d\.]+/ + end + + should "allow multiple timers to be set" do + app = lambda { |env| sleep 0.1; [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] } + runtime = Rack::Runtime.new(app, "App") + + # wrap many times to guarantee a measurable difference + 100.times do |i| + runtime = Rack::Runtime.new(runtime, i.to_s) + end + runtime = Rack::Runtime.new(runtime, "All") + + response = runtime.call({}) + + response[1]['X-Runtime-App'].should =~ /[\d\.]+/ + response[1]['X-Runtime-All'].should =~ /[\d\.]+/ + + Float(response[1]['X-Runtime-All']).should > Float(response[1]['X-Runtime-App']) + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_sendfile.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_sendfile.rb new file mode 100644 index 0000000..84517e7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_sendfile.rb @@ -0,0 +1,83 @@ +require 'rack/sendfile' +require 'rack/mock' + +describe Rack::File do + should "respond to #to_path" do + Rack::File.new(Dir.pwd).should.respond_to :to_path + end +end + +describe Rack::Sendfile do + def sendfile_body + res = ['Hello World'] + def res.to_path ; "/tmp/hello.txt" ; end + res + end + + def simple_app(body=sendfile_body) + lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] } + end + + def sendfile_app(body=sendfile_body) + Rack::Sendfile.new(simple_app(body)) + end + + @request = Rack::MockRequest.new(sendfile_app) + + def request(headers={}) + yield @request.get('/', headers) + end + + it "does nothing when no X-Sendfile-Type header present" do + request do |response| + response.should.be.ok + response.body.should.equal 'Hello World' + response.headers.should.not.include 'X-Sendfile' + end + end + + it "sets X-Sendfile response header and discards body" do + request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response| + response.should.be.ok + response.body.should.be.empty + response.headers['X-Sendfile'].should.equal '/tmp/hello.txt' + end + end + + it "sets X-Lighttpd-Send-File response header and discards body" do + request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response| + response.should.be.ok + response.body.should.be.empty + response.headers['X-Lighttpd-Send-File'].should.equal '/tmp/hello.txt' + end + end + + it "sets X-Accel-Redirect response header and discards body" do + headers = { + 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect', + 'HTTP_X_ACCEL_MAPPING' => '/tmp/=/foo/bar/' + } + request headers do |response| + response.should.be.ok + response.body.should.be.empty + response.headers['X-Accel-Redirect'].should.equal '/foo/bar/hello.txt' + end + end + + it 'writes to rack.error when no X-Accel-Mapping is specified' do + request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response| + response.should.be.ok + response.body.should.equal 'Hello World' + response.headers.should.not.include 'X-Accel-Redirect' + response.errors.should.include 'X-Accel-Mapping' + end + end + + it 'does nothing when body does not respond to #to_path' do + @request = Rack::MockRequest.new(sendfile_app(['Not a file...'])) + request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response| + response.body.should.equal 'Not a file...' + response.headers.should.not.include 'X-Sendfile' + end + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_server.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_server.rb new file mode 100644 index 0000000..9befacb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_server.rb @@ -0,0 +1,74 @@ +require 'rack' +require 'rack/server' +require 'tempfile' +require 'socket' +require 'open-uri' + +describe Rack::Server do + + def app + lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['success']] } + end + + it "overrides :config if :app is passed in" do + server = Rack::Server.new(:app => "FOO") + server.app.should == "FOO" + end + + should "not include Rack::Lint in deployment or none environments" do + server = Rack::Server.new(:app => 'foo') + server.middleware['deployment'].flatten.should.not.include(Rack::Lint) + server.middleware['none'].flatten.should.not.include(Rack::Lint) + end + + should "not include Rack::ShowExceptions in deployment or none environments" do + server = Rack::Server.new(:app => 'foo') + server.middleware['deployment'].flatten.should.not.include(Rack::ShowExceptions) + server.middleware['none'].flatten.should.not.include(Rack::ShowExceptions) + end + + should "support CGI" do + begin + o, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], 'foo' + server = Rack::Server.new(:app => 'foo') + server.server.name =~ /CGI/ + Rack::Server.logging_middleware.call(server).should.eql(nil) + ensure + ENV['REQUEST_METHOD'] = o + end + end + + should "not force any middleware under the none configuration" do + server = Rack::Server.new(:app => 'foo') + server.middleware['none'].should.be.empty + end + + should "use a full path to the pidfile" do + # avoids issues with daemonize chdir + opts = Rack::Server.new.send(:parse_options, %w[--pid testing.pid]) + opts[:pid].should.eql(::File.expand_path('testing.pid')) + end + + should "run a server" do + pidfile = Tempfile.open('pidfile') { |f| break f }.path + FileUtils.rm pidfile + server = Rack::Server.new( + :app => app, + :environment => 'none', + :pid => pidfile, + :Port => TCPServer.open('127.0.0.1', 0){|s| s.addr[1] }, + :Host => '127.0.0.1', + :daemonize => false, + :server => 'webrick' + ) + t = Thread.new { server.start } + until t.status == 'sleep'; t.join(0.01) end + body = open("http://127.0.0.1:#{server.options[:Port]}/") { |f| f.read } + body.should.eql('success') + + Process.kill(:INT, $$) + t.join + open(pidfile) { |f| f.read.should.eql $$.to_s } + end + +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_abstract_id.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_abstract_id.rb new file mode 100644 index 0000000..e189524 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_abstract_id.rb @@ -0,0 +1,43 @@ +### WARNING: there be hax in this file. + +require 'rack/session/abstract/id' + +describe Rack::Session::Abstract::ID do + id = Rack::Session::Abstract::ID + + def silence_warning + o, $VERBOSE = $VERBOSE, nil + yield + ensure + $VERBOSE = o + end + + def reload_id + $".delete $".find { |part| part =~ %r{session/abstract/id.rb} } + silence_warning { require 'rack/session/abstract/id' } + end + + should "use securerandom when available" do + begin + fake = false + silence_warning do + ::SecureRandom = fake = true unless defined?(SecureRandom) + end + reload_id + id::DEFAULT_OPTIONS[:secure_random].should.eql(fake || SecureRandom) + ensure + Object.send(:remove_const, :SecureRandom) if fake + end + end + + should "not use securerandom when unavailable" do + begin + sr = Object.send(:remove_const, :SecureRandom) if defined?(SecureRandom) + reload_id + id::DEFAULT_OPTIONS[:secure_random].should.eql false + ensure + ::SecureRandom = sr if defined?(sr) + end + end + +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_cookie.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_cookie.rb new file mode 100644 index 0000000..9fa8b49 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_cookie.rb @@ -0,0 +1,216 @@ +require 'rack/session/cookie' +require 'rack/mock' + +describe Rack::Session::Cookie do + incrementor = lambda do |env| + env["rack.session"]["counter"] ||= 0 + env["rack.session"]["counter"] += 1 + hash = env["rack.session"].dup + hash.delete("session_id") + Rack::Response.new(hash.inspect).to_a + end + + session_id = lambda do |env| + Rack::Response.new(env["rack.session"].inspect).to_a + end + + session_option = lambda do |opt| + lambda do |env| + Rack::Response.new(env["rack.session.options"][opt].inspect).to_a + end + end + + nothing = lambda do |env| + Rack::Response.new("Nothing").to_a + end + + describe 'Base64' do + it 'uses base64 to encode' do + coder = Rack::Session::Cookie::Base64.new + str = 'fuuuuu' + coder.encode(str).should.equal [str].pack('m') + end + + it 'uses base64 to decode' do + coder = Rack::Session::Cookie::Base64.new + str = ['fuuuuu'].pack('m') + coder.decode(str).should.equal str.unpack('m').first + end + + describe 'Marshal' do + it 'marshals and base64 encodes' do + coder = Rack::Session::Cookie::Base64::Marshal.new + str = 'fuuuuu' + coder.encode(str).should.equal [::Marshal.dump(str)].pack('m') + end + + it 'marshals and base64 decodes' do + coder = Rack::Session::Cookie::Base64::Marshal.new + str = [::Marshal.dump('fuuuuu')].pack('m') + coder.decode(str).should.equal ::Marshal.load(str.unpack('m').first) + end + + it 'rescues failures on decode' do + coder = Rack::Session::Cookie::Base64::Marshal.new + coder.decode('lulz').should.equal nil + end + end + end + + it 'uses a coder' do + identity = Class.new { + attr_reader :calls + + def initialize + @calls = [] + end + + def encode(str); @calls << :encode; str; end + def decode(str); @calls << :decode; str; end + }.new + cookie = Rack::Session::Cookie.new(incrementor, :coder => identity) + res = Rack::MockRequest.new(cookie).get("/") + res["Set-Cookie"].should.include("rack.session=") + res.body.should.equal '{"counter"=>1}' + identity.calls.should.equal [:decode, :encode] + end + + it "creates a new cookie" do + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/") + res["Set-Cookie"].should.include("rack.session=") + res.body.should.equal '{"counter"=>1}' + end + + it "loads from a cookie" do + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/") + cookie = res["Set-Cookie"] + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)). + get("/", "HTTP_COOKIE" => cookie) + res.body.should.equal '{"counter"=>2}' + cookie = res["Set-Cookie"] + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)). + get("/", "HTTP_COOKIE" => cookie) + res.body.should.equal '{"counter"=>3}' + end + + renewer = lambda do |env| + env["rack.session.options"][:renew] = true + Rack::Response.new("Nothing").to_a + end + + only_session_id = lambda do |env| + Rack::Response.new(env["rack.session"]["session_id"]).to_a + end + + it "renew session id" do + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/") + res = Rack::MockRequest.new(Rack::Session::Cookie.new(only_session_id)). + get("/", "HTTP_COOKIE" => res["Set-Cookie"]) + old_session_id = res.body + res = Rack::MockRequest.new(Rack::Session::Cookie.new(renewer)). + get("/", "HTTP_COOKIE" => res["Set-Cookie"]) + res = Rack::MockRequest.new(Rack::Session::Cookie.new(only_session_id)). + get("/", "HTTP_COOKIE" => res["Set-Cookie"]) + res.body.should.not.equal old_session_id + end + + it "survives broken cookies" do + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)). + get("/", "HTTP_COOKIE" => "rack.session=blarghfasel") + res.body.should.equal '{"counter"=>1}' + end + + bigcookie = lambda do |env| + env["rack.session"]["cookie"] = "big" * 3000 + Rack::Response.new(env["rack.session"].inspect).to_a + end + + it "barks on too big cookies" do + lambda{ + Rack::MockRequest.new(Rack::Session::Cookie.new(bigcookie)). + get("/", :fatal => true) + }.should.raise(Rack::MockRequest::FatalWarning) + end + + it "loads from a cookie wih integrity hash" do + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/") + cookie = res["Set-Cookie"] + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')). + get("/", "HTTP_COOKIE" => cookie) + res.body.should.equal '{"counter"=>2}' + cookie = res["Set-Cookie"] + res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')). + get("/", "HTTP_COOKIE" => cookie) + res.body.should.equal '{"counter"=>3}' + end + + it "ignores tampered with session cookies" do + app = Rack::Session::Cookie.new(incrementor, :secret => 'test') + response1 = Rack::MockRequest.new(app).get("/") + response1.body.should.equal '{"counter"=>1}' + + _, digest = response1["Set-Cookie"].split("--") + tampered_with_cookie = "hackerman-was-here" + "--" + digest + response2 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => + tampered_with_cookie) + + # Tampared cookie was ignored. Counter is back to 1. + response2.body.should.equal '{"counter"=>1}' + end + + it "returns the session id in the session hash" do + app = Rack::Session::Cookie.new(incrementor) + res = Rack::MockRequest.new(app).get("/") + res.body.should.equal '{"counter"=>1}' + + app = Rack::Session::Cookie.new(session_id) + res = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => res["Set-Cookie"]) + res.body.should.match(/"session_id"=>/) + res.body.should.match(/"counter"=>1/) + end + + it "does not return a cookie if set to secure but not using ssl" do + app = Rack::Session::Cookie.new(incrementor, :secure => true) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.be.nil + + res = Rack::MockRequest.new(app).get("/", "HTTPS" => "on") + res["Set-Cookie"].should.not.be.nil + end + + it "does not return a cookie if cookie was not read/written" do + app = Rack::Session::Cookie.new(nothing) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.be.nil + end + + it "does not return a cookie if cookie was not written (only read)" do + app = Rack::Session::Cookie.new(session_id) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.be.nil + end + + it "returns even if not read/written if :expire_after is set" do + app = Rack::Session::Cookie.new(nothing, :expire_after => 3600) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.not.be.nil + end + + it "exposes :secret in env['rack.session.option']" do + app = Rack::Session::Cookie.new(session_option[:secret], :secret => "foo") + res = Rack::MockRequest.new(app).get("/") + res.body.should == '"foo"' + end + + it "exposes :coder in env['rack.session.option']" do + app = Rack::Session::Cookie.new(session_option[:coder]) + res = Rack::MockRequest.new(app).get("/") + res.body.should.match(/Base64::Marshal/) + end + + it "allows passing in a hash with session data from middleware in front" do + app = Rack::Session::Cookie.new(session_id) + res = Rack::MockRequest.new(app).get("/", 'rack.session' => {:foo => 'bar'}) + res.body.should.match(/foo/) + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_memcache.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_memcache.rb new file mode 100644 index 0000000..7c81b9a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_memcache.rb @@ -0,0 +1,289 @@ +begin + require 'rack/session/memcache' + require 'rack/mock' + require 'thread' + + describe Rack::Session::Memcache do + session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key] + session_match = /#{session_key}=([0-9a-fA-F]+);/ + incrementor = lambda do |env| + env["rack.session"]["counter"] ||= 0 + env["rack.session"]["counter"] += 1 + Rack::Response.new(env["rack.session"].inspect).to_a + end + drop_session = proc do |env| + env['rack.session.options'][:drop] = true + incrementor.call(env) + end + renew_session = proc do |env| + env['rack.session.options'][:renew] = true + incrementor.call(env) + end + defer_session = proc do |env| + env['rack.session.options'][:defer] = true + incrementor.call(env) + end + + # test memcache connection + Rack::Session::Memcache.new(incrementor) + + it "faults on no connection" do + lambda{ + Rack::Session::Memcache.new(incrementor, :memcache_server => 'nosuchserver') + }.should.raise + end + + it "connects to existing server" do + test_pool = MemCache.new(incrementor, :namespace => 'test:rack:session') + test_pool.namespace.should.equal 'test:rack:session' + end + + it "passes options to MemCache" do + pool = Rack::Session::Memcache.new(incrementor, :namespace => 'test:rack:session') + pool.pool.namespace.should.equal 'test:rack:session' + end + + it "creates a new cookie" do + pool = Rack::Session::Memcache.new(incrementor) + res = Rack::MockRequest.new(pool).get("/") + res["Set-Cookie"].should.include("#{session_key}=") + res.body.should.equal '{"counter"=>1}' + end + + it "determines session from a cookie" do + pool = Rack::Session::Memcache.new(incrementor) + req = Rack::MockRequest.new(pool) + res = req.get("/") + cookie = res["Set-Cookie"] + req.get("/", "HTTP_COOKIE" => cookie). + body.should.equal '{"counter"=>2}' + req.get("/", "HTTP_COOKIE" => cookie). + body.should.equal '{"counter"=>3}' + end + + it "determines session only from a cookie by default" do + pool = Rack::Session::Memcache.new(incrementor) + req = Rack::MockRequest.new(pool) + res = req.get("/") + sid = res["Set-Cookie"][session_match, 1] + req.get("/?rack.session=#{sid}"). + body.should.equal '{"counter"=>1}' + req.get("/?rack.session=#{sid}"). + body.should.equal '{"counter"=>1}' + end + + it "determines session from params" do + pool = Rack::Session::Memcache.new(incrementor, :cookie_only => false) + req = Rack::MockRequest.new(pool) + res = req.get("/") + sid = res["Set-Cookie"][session_match, 1] + req.get("/?rack.session=#{sid}"). + body.should.equal '{"counter"=>2}' + req.get("/?rack.session=#{sid}"). + body.should.equal '{"counter"=>3}' + end + + it "survives nonexistant cookies" do + bad_cookie = "rack.session=blarghfasel" + pool = Rack::Session::Memcache.new(incrementor) + res = Rack::MockRequest.new(pool). + get("/", "HTTP_COOKIE" => bad_cookie) + res.body.should.equal '{"counter"=>1}' + cookie = res["Set-Cookie"][session_match] + cookie.should.not.match(/#{bad_cookie}/) + end + + it "maintains freshness" do + pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3) + res = Rack::MockRequest.new(pool).get('/') + res.body.should.include '"counter"=>1' + cookie = res["Set-Cookie"] + res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie) + res["Set-Cookie"].should.equal cookie + res.body.should.include '"counter"=>2' + puts 'Sleeping to expire session' if $DEBUG + sleep 4 + res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie) + res["Set-Cookie"].should.not.equal cookie + res.body.should.include '"counter"=>1' + end + + it "does not send the same session id if it did not change" do + pool = Rack::Session::Memcache.new(incrementor) + req = Rack::MockRequest.new(pool) + + res0 = req.get("/") + cookie = res0["Set-Cookie"][session_match] + res0.body.should.equal '{"counter"=>1}' + + res1 = req.get("/", "HTTP_COOKIE" => cookie) + res1["Set-Cookie"].should.be.nil + res1.body.should.equal '{"counter"=>2}' + + res2 = req.get("/", "HTTP_COOKIE" => cookie) + res2["Set-Cookie"].should.be.nil + res2.body.should.equal '{"counter"=>3}' + end + + it "deletes cookies with :drop option" do + pool = Rack::Session::Memcache.new(incrementor) + req = Rack::MockRequest.new(pool) + drop = Rack::Utils::Context.new(pool, drop_session) + dreq = Rack::MockRequest.new(drop) + + res1 = req.get("/") + session = (cookie = res1["Set-Cookie"])[session_match] + res1.body.should.equal '{"counter"=>1}' + + res2 = dreq.get("/", "HTTP_COOKIE" => cookie) + res2["Set-Cookie"].should.equal nil + res2.body.should.equal '{"counter"=>2}' + + res3 = req.get("/", "HTTP_COOKIE" => cookie) + res3["Set-Cookie"][session_match].should.not.equal session + res3.body.should.equal '{"counter"=>1}' + end + + it "provides new session id with :renew option" do + pool = Rack::Session::Memcache.new(incrementor) + req = Rack::MockRequest.new(pool) + renew = Rack::Utils::Context.new(pool, renew_session) + rreq = Rack::MockRequest.new(renew) + + res1 = req.get("/") + session = (cookie = res1["Set-Cookie"])[session_match] + res1.body.should.equal '{"counter"=>1}' + + res2 = rreq.get("/", "HTTP_COOKIE" => cookie) + new_cookie = res2["Set-Cookie"] + new_session = new_cookie[session_match] + new_session.should.not.equal session + res2.body.should.equal '{"counter"=>2}' + + res3 = req.get("/", "HTTP_COOKIE" => new_cookie) + res3.body.should.equal '{"counter"=>3}' + + # Old cookie was deleted + res4 = req.get("/", "HTTP_COOKIE" => cookie) + res4.body.should.equal '{"counter"=>1}' + end + + it "omits cookie with :defer option" do + pool = Rack::Session::Memcache.new(incrementor) + defer = Rack::Utils::Context.new(pool, defer_session) + dreq = Rack::MockRequest.new(defer) + + res0 = dreq.get("/") + res0["Set-Cookie"].should.equal nil + res0.body.should.equal '{"counter"=>1}' + end + + it "updates deep hashes correctly" do + hash_check = proc do |env| + session = env['rack.session'] + unless session.include? 'test' + session.update :a => :b, :c => { :d => :e }, + :f => { :g => { :h => :i} }, 'test' => true + else + session[:f][:g][:h] = :j + end + [200, {}, [session.inspect]] + end + pool = Rack::Session::Memcache.new(hash_check) + req = Rack::MockRequest.new(pool) + + res0 = req.get("/") + session_id = (cookie = res0["Set-Cookie"])[session_match, 1] + ses0 = pool.pool.get(session_id, true) + + req.get("/", "HTTP_COOKIE" => cookie) + ses1 = pool.pool.get(session_id, true) + + ses1.should.not.equal ses0 + end + + # anyone know how to do this better? + it "cleanly merges sessions when multithreaded" do + unless $DEBUG + 1.should.equal 1 # fake assertion to appease the mighty bacon + next + end + warn 'Running multithread test for Session::Memcache' + pool = Rack::Session::Memcache.new(incrementor) + req = Rack::MockRequest.new(pool) + + res = req.get('/') + res.body.should.equal '{"counter"=>1}' + cookie = res["Set-Cookie"] + session_id = cookie[session_match, 1] + + delta_incrementor = lambda do |env| + # emulate disconjoinment of threading + env['rack.session'] = env['rack.session'].dup + Thread.stop + env['rack.session'][(Time.now.usec*rand).to_i] = true + incrementor.call(env) + end + tses = Rack::Utils::Context.new pool, delta_incrementor + treq = Rack::MockRequest.new(tses) + tnum = rand(7).to_i+5 + r = Array.new(tnum) do + Thread.new(treq) do |run| + run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) + end + end.reverse.map{|t| t.run.join.value } + r.each do |request| + request['Set-Cookie'].should.equal cookie + request.body.should.include '"counter"=>2' + end + + session = pool.pool.get(session_id) + session.size.should.equal tnum+1 # counter + session['counter'].should.equal 2 # meeeh + + tnum = rand(7).to_i+5 + r = Array.new(tnum) do |i| + app = Rack::Utils::Context.new pool, time_delta + req = Rack::MockRequest.new app + Thread.new(req) do |run| + run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) + end + end.reverse.map{|t| t.run.join.value } + r.each do |request| + request['Set-Cookie'].should.equal cookie + request.body.should.include '"counter"=>3' + end + + session = pool.pool.get(session_id) + session.size.should.be tnum+1 + session['counter'].should.be 3 + + drop_counter = proc do |env| + env['rack.session'].delete 'counter' + env['rack.session']['foo'] = 'bar' + [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect] + end + tses = Rack::Utils::Context.new pool, drop_counter + treq = Rack::MockRequest.new(tses) + tnum = rand(7).to_i+5 + r = Array.new(tnum) do + Thread.new(treq) do |run| + run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) + end + end.reverse.map{|t| t.run.join.value } + r.each do |request| + request['Set-Cookie'].should.equal cookie + request.body.should.include '"foo"=>"bar"' + end + + session = pool.pool.get(session_id) + session.size.should.be r.size+1 + session['counter'].should.be.nil? + session['foo'].should.equal 'bar' + end + end +rescue RuntimeError + $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again." +rescue LoadError + $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again." +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_pool.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_pool.rb new file mode 100644 index 0000000..b498806 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_session_pool.rb @@ -0,0 +1,200 @@ +require 'thread' +require 'rack/mock' +require 'rack/session/pool' + +describe Rack::Session::Pool do + session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key] + session_match = /#{session_key}=[0-9a-fA-F]+;/ + + incrementor = lambda do |env| + env["rack.session"]["counter"] ||= 0 + env["rack.session"]["counter"] += 1 + Rack::Response.new(env["rack.session"].inspect).to_a + end + + session_id = lambda do |env| + Rack::Response.new(env["rack.session"].inspect).to_a + end + + nothing = lambda do |env| + Rack::Response.new("Nothing").to_a + end + + drop_session = lambda do |env| + env['rack.session.options'][:drop] = true + incrementor.call(env) + end + + renew_session = lambda do |env| + env['rack.session.options'][:renew] = true + incrementor.call(env) + end + + defer_session = lambda do |env| + env['rack.session.options'][:defer] = true + incrementor.call(env) + end + + it "creates a new cookie" do + pool = Rack::Session::Pool.new(incrementor) + res = Rack::MockRequest.new(pool).get("/") + res["Set-Cookie"].should.match session_match + res.body.should.equal '{"counter"=>1}' + end + + it "determines session from a cookie" do + pool = Rack::Session::Pool.new(incrementor) + req = Rack::MockRequest.new(pool) + cookie = req.get("/")["Set-Cookie"] + req.get("/", "HTTP_COOKIE" => cookie). + body.should.equal '{"counter"=>2}' + req.get("/", "HTTP_COOKIE" => cookie). + body.should.equal '{"counter"=>3}' + end + + it "survives nonexistant cookies" do + pool = Rack::Session::Pool.new(incrementor) + res = Rack::MockRequest.new(pool). + get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel") + res.body.should.equal '{"counter"=>1}' + end + + it "does not send the same session id if it did not change" do + pool = Rack::Session::Pool.new(incrementor) + req = Rack::MockRequest.new(pool) + + res0 = req.get("/") + cookie = res0["Set-Cookie"][session_match] + res0.body.should.equal '{"counter"=>1}' + pool.pool.size.should.equal 1 + + res1 = req.get("/", "HTTP_COOKIE" => cookie) + res1["Set-Cookie"].should.be.nil + res1.body.should.equal '{"counter"=>2}' + pool.pool.size.should.equal 1 + + res2 = req.get("/", "HTTP_COOKIE" => cookie) + res2["Set-Cookie"].should.be.nil + res2.body.should.equal '{"counter"=>3}' + pool.pool.size.should.equal 1 + end + + it "deletes cookies with :drop option" do + pool = Rack::Session::Pool.new(incrementor) + req = Rack::MockRequest.new(pool) + drop = Rack::Utils::Context.new(pool, drop_session) + dreq = Rack::MockRequest.new(drop) + + res1 = req.get("/") + session = (cookie = res1["Set-Cookie"])[session_match] + res1.body.should.equal '{"counter"=>1}' + pool.pool.size.should.equal 1 + + res2 = dreq.get("/", "HTTP_COOKIE" => cookie) + res2["Set-Cookie"].should.be.nil + res2.body.should.equal '{"counter"=>2}' + pool.pool.size.should.equal 0 + + res3 = req.get("/", "HTTP_COOKIE" => cookie) + res3["Set-Cookie"][session_match].should.not.equal session + res3.body.should.equal '{"counter"=>1}' + pool.pool.size.should.equal 1 + end + + it "provides new session id with :renew option" do + pool = Rack::Session::Pool.new(incrementor) + req = Rack::MockRequest.new(pool) + renew = Rack::Utils::Context.new(pool, renew_session) + rreq = Rack::MockRequest.new(renew) + + res1 = req.get("/") + session = (cookie = res1["Set-Cookie"])[session_match] + res1.body.should.equal '{"counter"=>1}' + pool.pool.size.should.equal 1 + + res2 = rreq.get("/", "HTTP_COOKIE" => cookie) + new_cookie = res2["Set-Cookie"] + new_session = new_cookie[session_match] + new_session.should.not.equal session + res2.body.should.equal '{"counter"=>2}' + pool.pool.size.should.equal 1 + + res3 = req.get("/", "HTTP_COOKIE" => new_cookie) + res3.body.should.equal '{"counter"=>3}' + pool.pool.size.should.equal 1 + + res4 = req.get("/", "HTTP_COOKIE" => cookie) + res4.body.should.equal '{"counter"=>1}' + pool.pool.size.should.equal 2 + end + + it "omits cookie with :defer option" do + pool = Rack::Session::Pool.new(incrementor) + defer = Rack::Utils::Context.new(pool, defer_session) + dreq = Rack::MockRequest.new(defer) + + res1 = dreq.get("/") + res1["Set-Cookie"].should.equal nil + res1.body.should.equal '{"counter"=>1}' + pool.pool.size.should.equal 1 + end + + # anyone know how to do this better? + it "should merge sessions when multithreaded" do + unless $DEBUG + 1.should.equal 1 + next + end + + warn 'Running multithread tests for Session::Pool' + pool = Rack::Session::Pool.new(incrementor) + req = Rack::MockRequest.new(pool) + + res = req.get('/') + res.body.should.equal '{"counter"=>1}' + cookie = res["Set-Cookie"] + sess_id = cookie[/#{pool.key}=([^,;]+)/,1] + + delta_incrementor = lambda do |env| + # emulate disconjoinment of threading + env['rack.session'] = env['rack.session'].dup + Thread.stop + env['rack.session'][(Time.now.usec*rand).to_i] = true + incrementor.call(env) + end + tses = Rack::Utils::Context.new pool, delta_incrementor + treq = Rack::MockRequest.new(tses) + tnum = rand(7).to_i+5 + r = Array.new(tnum) do + Thread.new(treq) do |run| + run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) + end + end.reverse.map{|t| t.run.join.value } + r.each do |resp| + resp['Set-Cookie'].should.equal cookie + resp.body.should.include '"counter"=>2' + end + + session = pool.pool[sess_id] + session.size.should.equal tnum+1 # counter + session['counter'].should.equal 2 # meeeh + end + + it "does not return a cookie if cookie was not read/written" do + app = Rack::Session::Cookie.new(nothing) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.be.nil + end + + it "does not return a cookie if cookie was not written (only read)" do + app = Rack::Session::Cookie.new(session_id) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.be.nil + end + + it "returns even if not read/written if :expire_after is set" do + app = Rack::Session::Cookie.new(nothing, :expire_after => 3600) + res = Rack::MockRequest.new(app).get("/") + res["Set-Cookie"].should.not.be.nil + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_showexceptions.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_showexceptions.rb new file mode 100644 index 0000000..5bfc952 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_showexceptions.rb @@ -0,0 +1,87 @@ +require 'rack/showexceptions' +require 'rack/mock' + +describe Rack::ShowExceptions do + it "catches exceptions" do + res = nil + + req = Rack::MockRequest.new( + Rack::ShowExceptions.new( + lambda{|env| raise RuntimeError } + )) + + lambda{ + res = req.get("/") + }.should.not.raise + + res.should.be.a.server_error + res.status.should.equal 500 + + res.should =~ /RuntimeError/ + res.should =~ /ShowExceptions/ + end + + it "responds with plain text on AJAX requests accepting anything but HTML" do + res = nil + + req = Rack::MockRequest.new( + Rack::ShowExceptions.new( + lambda{|env| raise RuntimeError, "It was never supposed to work" } + )) + + lambda{ + res = req.get("/", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest") + }.should.not.raise + + res.should.be.a.server_error + res.status.should.equal 500 + + res.content_type.should.equal "text/plain" + + res.body.should.include "RuntimeError: It was never supposed to work\n" + res.body.should.include __FILE__ + end + + it "responds with HTML on AJAX requests accepting HTML" do + res = nil + + req = Rack::MockRequest.new( + Rack::ShowExceptions.new( + lambda{|env| raise RuntimeError, "It was never supposed to work" } + )) + + lambda{ + res = req.get("/", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", "HTTP_ACCEPT" => "text/html") + }.should.not.raise + + res.should.be.a.server_error + res.status.should.equal 500 + + res.content_type.should.equal "text/html" + + res.body.should.include "RuntimeError" + res.body.should.include "It was never supposed to work" + res.body.should.include Rack::Utils.escape_html(__FILE__) + end + + it "handles exceptions without a backtrace" do + res = nil + + req = Rack::MockRequest.new( + Rack::ShowExceptions.new( + lambda{|env| raise RuntimeError, "", [] } + ) + ) + + lambda{ + res = req.get("/") + }.should.not.raise + + res.should.be.a.server_error + res.status.should.equal 500 + + res.should =~ /RuntimeError/ + res.should =~ /ShowExceptions/ + res.should =~ /unknown location/ + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_showstatus.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_showstatus.rb new file mode 100644 index 0000000..210a2f4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_showstatus.rb @@ -0,0 +1,79 @@ +require 'rack/showstatus' +require 'rack/mock' + +describe Rack::ShowStatus do + should "provide a default status message" do + req = Rack::MockRequest.new( + Rack::ShowStatus.new(lambda{|env| + [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []] + })) + + res = req.get("/", :lint => true) + res.should.be.not_found + res.should.be.not.empty + + res["Content-Type"].should.equal("text/html") + res.should =~ /404/ + res.should =~ /Not Found/ + end + + should "let the app provide additional information" do + req = Rack::MockRequest.new( + Rack::ShowStatus.new( + lambda{|env| + env["rack.showstatus.detail"] = "gone too meta." + [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []] + })) + + res = req.get("/", :lint => true) + res.should.be.not_found + res.should.be.not.empty + + res["Content-Type"].should.equal("text/html") + res.should =~ /404/ + res.should =~ /Not Found/ + res.should =~ /too meta/ + end + + should "not replace existing messages" do + req = Rack::MockRequest.new( + Rack::ShowStatus.new( + lambda{|env| + [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]] + })) + + res = req.get("/", :lint => true) + res.should.be.not_found + + res.body.should == "foo!" + end + + should "pass on original headers" do + headers = {"WWW-Authenticate" => "Basic blah"} + + req = Rack::MockRequest.new( + Rack::ShowStatus.new(lambda{|env| [401, headers, []] })) + res = req.get("/", :lint => true) + + res["WWW-Authenticate"].should.equal("Basic blah") + end + + should "replace existing messages if there is detail" do + req = Rack::MockRequest.new( + Rack::ShowStatus.new( + lambda{|env| + env["rack.showstatus.detail"] = "gone too meta." + [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]] + })) + + res = req.get("/", :lint => true) + res.should.be.not_found + res.should.be.not.empty + + res["Content-Type"].should.equal("text/html") + res["Content-Length"].should.not.equal("4") + res.should =~ /404/ + res.should =~ /too meta/ + res.body.should.not =~ /foo/ + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_static.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_static.rb new file mode 100644 index 0000000..651c9f4 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_static.rb @@ -0,0 +1,56 @@ +require 'rack/static' +require 'rack/mock' + +class DummyApp + def call(env) + [200, {}, ["Hello World"]] + end +end + +describe Rack::Static do + root = File.expand_path(File.dirname(__FILE__)) + + OPTIONS = {:urls => ["/cgi"], :root => root} + HASH_OPTIONS = {:urls => {"/cgi/sekret" => 'cgi/test'}, :root => root} + + @request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, OPTIONS)) + @hash_request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, HASH_OPTIONS)) + + it "serves files" do + res = @request.get("/cgi/test") + res.should.be.ok + res.body.should =~ /ruby/ + end + + it "404s if url root is known but it can't find the file" do + res = @request.get("/cgi/foo") + res.should.be.not_found + end + + it "calls down the chain if url root is not known" do + res = @request.get("/something/else") + res.should.be.ok + res.body.should == "Hello World" + end + + it "serves hidden files" do + res = @hash_request.get("/cgi/sekret") + res.should.be.ok + res.body.should =~ /ruby/ + end + + it "calls down the chain if the URI is not specified" do + res = @hash_request.get("/something/else") + res.should.be.ok + res.body.should == "Hello World" + end + + it "supports serving fixed cache-control" do + opts = OPTIONS.merge(:cache_control => 'public') + request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, opts)) + res = request.get("/cgi/test") + res.should.be.ok + res.headers['Cache-Control'].should == 'public' + end + +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_thin.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_thin.rb new file mode 100644 index 0000000..9403964 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_thin.rb @@ -0,0 +1,86 @@ +begin +require 'rack/handler/thin' +require File.expand_path('../testrequest', __FILE__) +require 'timeout' + +describe Rack::Handler::Thin do + extend TestRequest::Helpers + + @app = Rack::Lint.new(TestRequest.new) + @server = nil + Thin::Logging.silent = true + + @thread = Thread.new do + Rack::Handler::Thin.run(@app, :Host => @host='0.0.0.0', :Port => @port=9204) do |server| + @server = server + end + end + + Thread.pass until @server && @server.running? + + should "respond" do + GET("/") + response.should.not.be.nil + end + + should "be a Thin" do + GET("/") + status.should.equal 200 + response["SERVER_SOFTWARE"].should =~ /thin/ + response["HTTP_VERSION"].should.equal "HTTP/1.1" + response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" + response["SERVER_PORT"].should.equal "9204" + response["SERVER_NAME"].should.equal "0.0.0.0" + end + + should "have rack headers" do + GET("/") + response["rack.version"].should.equal [1,0] + response["rack.multithread"].should.equal false + response["rack.multiprocess"].should.equal false + response["rack.run_once"].should.equal false + end + + should "have CGI headers on GET" do + GET("/") + response["REQUEST_METHOD"].should.equal "GET" + response["REQUEST_PATH"].should.equal "/" + response["PATH_INFO"].should.be.equal "/" + response["QUERY_STRING"].should.equal "" + response["test.postdata"].should.equal "" + + GET("/test/foo?quux=1") + response["REQUEST_METHOD"].should.equal "GET" + response["REQUEST_PATH"].should.equal "/test/foo" + response["PATH_INFO"].should.equal "/test/foo" + response["QUERY_STRING"].should.equal "quux=1" + end + + should "have CGI headers on POST" do + POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) + status.should.equal 200 + response["REQUEST_METHOD"].should.equal "POST" + response["REQUEST_PATH"].should.equal "/" + response["QUERY_STRING"].should.equal "" + response["HTTP_X_TEST_HEADER"].should.equal "42" + response["test.postdata"].should.equal "rack-form-data=23" + end + + should "support HTTP auth" do + GET("/test", {:user => "ruth", :passwd => "secret"}) + response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" + end + + should "set status" do + GET("/test?secret") + status.should.equal 403 + response["rack.url_scheme"].should.equal "http" + end + + @server.stop! + @thread.kill +end + +rescue LoadError + $stderr.puts "Skipping Rack::Handler::Thin tests (Thin is required). `gem install thin` and try again." +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_urlmap.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_urlmap.rb new file mode 100644 index 0000000..fdaf129 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_urlmap.rb @@ -0,0 +1,213 @@ +require 'rack/urlmap' +require 'rack/mock' + +describe Rack::URLMap do + it "dispatches paths correctly" do + app = lambda { |env| + [200, { + 'X-ScriptName' => env['SCRIPT_NAME'], + 'X-PathInfo' => env['PATH_INFO'], + 'Content-Type' => 'text/plain' + }, [""]] + } + map = Rack::URLMap.new({ + 'http://foo.org/bar' => app, + '/foo' => app, + '/foo/bar' => app + }) + + res = Rack::MockRequest.new(map).get("/") + res.should.be.not_found + + res = Rack::MockRequest.new(map).get("/qux") + res.should.be.not_found + + res = Rack::MockRequest.new(map).get("/foo") + res.should.be.ok + res["X-ScriptName"].should.equal "/foo" + res["X-PathInfo"].should.equal "" + + res = Rack::MockRequest.new(map).get("/foo/") + res.should.be.ok + res["X-ScriptName"].should.equal "/foo" + res["X-PathInfo"].should.equal "/" + + res = Rack::MockRequest.new(map).get("/foo/bar") + res.should.be.ok + res["X-ScriptName"].should.equal "/foo/bar" + res["X-PathInfo"].should.equal "" + + res = Rack::MockRequest.new(map).get("/foo/bar/") + res.should.be.ok + res["X-ScriptName"].should.equal "/foo/bar" + res["X-PathInfo"].should.equal "/" + + res = Rack::MockRequest.new(map).get("/foo///bar//quux") + res.status.should.equal 200 + res.should.be.ok + res["X-ScriptName"].should.equal "/foo/bar" + res["X-PathInfo"].should.equal "//quux" + + res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh") + res.should.be.ok + res["X-ScriptName"].should.equal "/bleh/foo" + res["X-PathInfo"].should.equal "/quux" + + res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org') + res.should.be.ok + res["X-ScriptName"].should.equal "/bar" + res["X-PathInfo"].should.be.empty + + res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org') + res.should.be.ok + res["X-ScriptName"].should.equal "/bar" + res["X-PathInfo"].should.equal '/' + end + + + it "dispatches hosts correctly" do + map = Rack::URLMap.new("http://foo.org/" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "foo.org", + "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + }, [""]]}, + "http://subdomain.foo.org/" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "subdomain.foo.org", + "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + }, [""]]}, + "http://bar.org/" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "bar.org", + "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + }, [""]]}, + "/" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "default.org", + "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + }, [""]]} + ) + + res = Rack::MockRequest.new(map).get("/") + res.should.be.ok + res["X-Position"].should.equal "default.org" + + res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org") + res.should.be.ok + res["X-Position"].should.equal "bar.org" + + res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org") + res.should.be.ok + res["X-Position"].should.equal "foo.org" + + res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org") + res.should.be.ok + res["X-Position"].should.equal "subdomain.foo.org" + + res = Rack::MockRequest.new(map).get("http://foo.org/") + res.should.be.ok + res["X-Position"].should.equal "default.org" + + res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org") + res.should.be.ok + res["X-Position"].should.equal "default.org" + + res = Rack::MockRequest.new(map).get("/", + "HTTP_HOST" => "example.org:9292", + "SERVER_PORT" => "9292") + res.should.be.ok + res["X-Position"].should.equal "default.org" + end + + should "be nestable" do + map = Rack::URLMap.new("/foo" => + Rack::URLMap.new("/bar" => + Rack::URLMap.new("/quux" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "/foo/bar/quux", + "X-PathInfo" => env["PATH_INFO"], + "X-ScriptName" => env["SCRIPT_NAME"], + }, [""]]} + ))) + + res = Rack::MockRequest.new(map).get("/foo/bar") + res.should.be.not_found + + res = Rack::MockRequest.new(map).get("/foo/bar/quux") + res.should.be.ok + res["X-Position"].should.equal "/foo/bar/quux" + res["X-PathInfo"].should.equal "" + res["X-ScriptName"].should.equal "/foo/bar/quux" + end + + should "route root apps correctly" do + map = Rack::URLMap.new("/" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "root", + "X-PathInfo" => env["PATH_INFO"], + "X-ScriptName" => env["SCRIPT_NAME"] + }, [""]]}, + "/foo" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "foo", + "X-PathInfo" => env["PATH_INFO"], + "X-ScriptName" => env["SCRIPT_NAME"] + }, [""]]} + ) + + res = Rack::MockRequest.new(map).get("/foo/bar") + res.should.be.ok + res["X-Position"].should.equal "foo" + res["X-PathInfo"].should.equal "/bar" + res["X-ScriptName"].should.equal "/foo" + + res = Rack::MockRequest.new(map).get("/foo") + res.should.be.ok + res["X-Position"].should.equal "foo" + res["X-PathInfo"].should.equal "" + res["X-ScriptName"].should.equal "/foo" + + res = Rack::MockRequest.new(map).get("/bar") + res.should.be.ok + res["X-Position"].should.equal "root" + res["X-PathInfo"].should.equal "/bar" + res["X-ScriptName"].should.equal "" + + res = Rack::MockRequest.new(map).get("") + res.should.be.ok + res["X-Position"].should.equal "root" + res["X-PathInfo"].should.equal "/" + res["X-ScriptName"].should.equal "" + end + + should "not squeeze slashes" do + map = Rack::URLMap.new("/" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "root", + "X-PathInfo" => env["PATH_INFO"], + "X-ScriptName" => env["SCRIPT_NAME"] + }, [""]]}, + "/foo" => lambda { |env| + [200, + { "Content-Type" => "text/plain", + "X-Position" => "foo", + "X-PathInfo" => env["PATH_INFO"], + "X-ScriptName" => env["SCRIPT_NAME"] + }, [""]]} + ) + + res = Rack::MockRequest.new(map).get("/http://example.org/bar") + res.should.be.ok + res["X-Position"].should.equal "root" + res["X-PathInfo"].should.equal "/http://example.org/bar" + res["X-ScriptName"].should.equal "" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_utils.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_utils.rb new file mode 100644 index 0000000..0e8935f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_utils.rb @@ -0,0 +1,494 @@ +# -*- encoding: utf-8 -*- +require 'rack/utils' +require 'rack/mock' + +describe Rack::Utils do + def kcodeu + one8 = RUBY_VERSION.to_f < 1.9 + default_kcode, $KCODE = $KCODE, 'U' if one8 + yield + ensure + $KCODE = default_kcode if one8 + end + + should "escape correctly" do + Rack::Utils.escape("fobar").should.equal "fo%3Co%3Ebar" + Rack::Utils.escape("a space").should.equal "a+space" + Rack::Utils.escape("q1!2\"'w$5&7/z8)?\\"). + should.equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C" + end + + should "escape correctly for multibyte characters" do + matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto + matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding + Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8' + matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto + matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding + Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8' + end + + if RUBY_VERSION[/^\d+\.\d+/] == '1.8' + should "escape correctly for multibyte characters if $KCODE is set to 'U'" do + kcodeu do + matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto + matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding + Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8' + matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto + matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding + Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8' + end + end + + should "unescape multibyte characters correctly if $KCODE is set to 'U'" do + kcodeu do + Rack::Utils.unescape('%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8').should.equal( + "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0]) + end + end + end + + should "escape objects that responds to to_s" do + kcodeu do + Rack::Utils.escape(:id).should.equal "id" + end + end + + if "".respond_to?(:encode) + should "escape non-UTF8 strings" do + Rack::Utils.escape("ø".encode("ISO-8859-1")).should.equal "%F8" + end + end + + should "not hang on escaping long strings that end in % (http://redmine.ruby-lang.org/issues/5149)" do + lambda { + timeout(1) do + lambda { + URI.decode_www_form_component "A string that causes catastrophic backtracking as it gets longer %" + }.should.raise(ArgumentError) + end + }.should.not.raise(Timeout::Error) + end + + should "escape path spaces with %20" do + Rack::Utils.escape_path("foo bar").should.equal "foo%20bar" + end + + should "unescape correctly" do + Rack::Utils.unescape("fo%3Co%3Ebar").should.equal "fobar" + Rack::Utils.unescape("a+space").should.equal "a space" + Rack::Utils.unescape("a%20space").should.equal "a space" + Rack::Utils.unescape("q1%212%22%27w%245%267%2Fz8%29%3F%5C"). + should.equal "q1!2\"'w$5&7/z8)?\\" + end + + should "parse query strings correctly" do + Rack::Utils.parse_query("foo=bar"). + should.equal "foo" => "bar" + Rack::Utils.parse_query("foo=\"bar\""). + should.equal "foo" => "\"bar\"" + Rack::Utils.parse_query("foo=bar&foo=quux"). + should.equal "foo" => ["bar", "quux"] + Rack::Utils.parse_query("foo=1&bar=2"). + should.equal "foo" => "1", "bar" => "2" + Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"). + should.equal "my weird field" => "q1!2\"'w$5&7/z8)?" + Rack::Utils.parse_query("foo%3Dbaz=bar").should.equal "foo=baz" => "bar" + end + + should "parse nested query strings correctly" do + Rack::Utils.parse_nested_query("foo"). + should.equal "foo" => nil + Rack::Utils.parse_nested_query("foo="). + should.equal "foo" => "" + Rack::Utils.parse_nested_query("foo=bar"). + should.equal "foo" => "bar" + Rack::Utils.parse_nested_query("foo=\"bar\""). + should.equal "foo" => "\"bar\"" + + Rack::Utils.parse_nested_query("foo=bar&foo=quux"). + should.equal "foo" => "quux" + Rack::Utils.parse_nested_query("foo&foo="). + should.equal "foo" => "" + Rack::Utils.parse_nested_query("foo=1&bar=2"). + should.equal "foo" => "1", "bar" => "2" + Rack::Utils.parse_nested_query("&foo=1&&bar=2"). + should.equal "foo" => "1", "bar" => "2" + Rack::Utils.parse_nested_query("foo&bar="). + should.equal "foo" => nil, "bar" => "" + Rack::Utils.parse_nested_query("foo=bar&baz="). + should.equal "foo" => "bar", "baz" => "" + Rack::Utils.parse_nested_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"). + should.equal "my weird field" => "q1!2\"'w$5&7/z8)?" + + Rack::Utils.parse_nested_query("a=b&pid%3D1234=1023"). + should.equal "pid=1234" => "1023", "a" => "b" + + Rack::Utils.parse_nested_query("foo[]"). + should.equal "foo" => [nil] + Rack::Utils.parse_nested_query("foo[]="). + should.equal "foo" => [""] + Rack::Utils.parse_nested_query("foo[]=bar"). + should.equal "foo" => ["bar"] + + Rack::Utils.parse_nested_query("foo[]=1&foo[]=2"). + should.equal "foo" => ["1", "2"] + Rack::Utils.parse_nested_query("foo=bar&baz[]=1&baz[]=2&baz[]=3"). + should.equal "foo" => "bar", "baz" => ["1", "2", "3"] + Rack::Utils.parse_nested_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3"). + should.equal "foo" => ["bar"], "baz" => ["1", "2", "3"] + + Rack::Utils.parse_nested_query("x[y][z]=1"). + should.equal "x" => {"y" => {"z" => "1"}} + Rack::Utils.parse_nested_query("x[y][z][]=1"). + should.equal "x" => {"y" => {"z" => ["1"]}} + Rack::Utils.parse_nested_query("x[y][z]=1&x[y][z]=2"). + should.equal "x" => {"y" => {"z" => "2"}} + Rack::Utils.parse_nested_query("x[y][z][]=1&x[y][z][]=2"). + should.equal "x" => {"y" => {"z" => ["1", "2"]}} + + Rack::Utils.parse_nested_query("x[y][][z]=1"). + should.equal "x" => {"y" => [{"z" => "1"}]} + Rack::Utils.parse_nested_query("x[y][][z][]=1"). + should.equal "x" => {"y" => [{"z" => ["1"]}]} + Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=2"). + should.equal "x" => {"y" => [{"z" => "1", "w" => "2"}]} + + Rack::Utils.parse_nested_query("x[y][][v][w]=1"). + should.equal "x" => {"y" => [{"v" => {"w" => "1"}}]} + Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][v][w]=2"). + should.equal "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]} + + Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][z]=2"). + should.equal "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]} + Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3"). + should.equal "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]} + + lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y]z=2") }. + should.raise(TypeError). + message.should.equal "expected Hash (got String) for param `y'" + + lambda { Rack::Utils.parse_nested_query("x[y]=1&x[]=1") }. + should.raise(TypeError). + message.should.equal "expected Array (got Hash) for param `x'" + + lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y][][w]=2") }. + should.raise(TypeError). + message.should.equal "expected Array (got String) for param `y'" + end + + should "build query strings correctly" do + Rack::Utils.build_query("foo" => "bar").should.equal "foo=bar" + Rack::Utils.build_query("foo" => ["bar", "quux"]). + should.equal "foo=bar&foo=quux" + Rack::Utils.build_query("foo" => "1", "bar" => "2"). + should.equal "foo=1&bar=2" + Rack::Utils.build_query("my weird field" => "q1!2\"'w$5&7/z8)?"). + should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F" + end + + should "build nested query strings correctly" do + Rack::Utils.build_nested_query("foo" => nil).should.equal "foo" + Rack::Utils.build_nested_query("foo" => "").should.equal "foo=" + Rack::Utils.build_nested_query("foo" => "bar").should.equal "foo=bar" + + Rack::Utils.build_nested_query("foo" => "1", "bar" => "2"). + should.equal "foo=1&bar=2" + Rack::Utils.build_nested_query("my weird field" => "q1!2\"'w$5&7/z8)?"). + should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F" + + Rack::Utils.build_nested_query("foo" => [nil]). + should.equal "foo[]" + Rack::Utils.build_nested_query("foo" => [""]). + should.equal "foo[]=" + Rack::Utils.build_nested_query("foo" => ["bar"]). + should.equal "foo[]=bar" + + # The ordering of the output query string is unpredictable with 1.8's + # unordered hash. Test that build_nested_query performs the inverse + # function of parse_nested_query. + [{"foo" => nil, "bar" => ""}, + {"foo" => "bar", "baz" => ""}, + {"foo" => ["1", "2"]}, + {"foo" => "bar", "baz" => ["1", "2", "3"]}, + {"foo" => ["bar"], "baz" => ["1", "2", "3"]}, + {"foo" => ["1", "2"]}, + {"foo" => "bar", "baz" => ["1", "2", "3"]}, + {"x" => {"y" => {"z" => "1"}}}, + {"x" => {"y" => {"z" => ["1"]}}}, + {"x" => {"y" => {"z" => ["1", "2"]}}}, + {"x" => {"y" => [{"z" => "1"}]}}, + {"x" => {"y" => [{"z" => ["1"]}]}}, + {"x" => {"y" => [{"z" => "1", "w" => "2"}]}}, + {"x" => {"y" => [{"v" => {"w" => "1"}}]}}, + {"x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}}, + {"x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}}, + {"x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}} + ].each { |params| + qs = Rack::Utils.build_nested_query(params) + Rack::Utils.parse_nested_query(qs).should.equal params + } + + lambda { Rack::Utils.build_nested_query("foo=bar") }. + should.raise(ArgumentError). + message.should.equal "value must be a Hash" + end + + should "escape html entities [&><'\"/]" do + Rack::Utils.escape_html("foo").should.equal "foo" + Rack::Utils.escape_html("f&o").should.equal "f&o" + Rack::Utils.escape_html("fo").should.equal "f>o" + Rack::Utils.escape_html("f'o").should.equal "f'o" + Rack::Utils.escape_html('f"o').should.equal "f"o" + Rack::Utils.escape_html("f/o").should.equal "f/o" + Rack::Utils.escape_html("").should.equal "<foo></foo>" + end + + should "escape html entities even on MRI when it's bugged" do + test_escape = lambda do + kcodeu do + Rack::Utils.escape_html("\300<").should.equal "\300<" + end + end + + if RUBY_VERSION.to_f < 1.9 + test_escape.call + else + test_escape.should.raise(ArgumentError) + end + end + + if "".respond_to?(:encode) + should "escape html entities in unicode strings" do + # the following will cause warnings if the regex is poorly encoded: + Rack::Utils.escape_html("☃").should.equal "☃" + end + end + + should "figure out which encodings are acceptable" do + helper = lambda do |a, b| + Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => a)) + Rack::Utils.select_best_encoding(a, b) + end + + helper.call(%w(), [["x", 1]]).should.equal(nil) + helper.call(%w(identity), [["identity", 0.0]]).should.equal(nil) + helper.call(%w(identity), [["*", 0.0]]).should.equal(nil) + + helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("identity") + + helper.call(%w(compress gzip identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("compress") + helper.call(%w(compress gzip identity), [["compress", 0.5], ["gzip", 1.0]]).should.equal("gzip") + + helper.call(%w(foo bar identity), []).should.equal("identity") + helper.call(%w(foo bar identity), [["*", 1.0]]).should.equal("foo") + helper.call(%w(foo bar identity), [["*", 1.0], ["foo", 0.9]]).should.equal("bar") + + helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).should.equal("identity") + helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).should.equal("identity") + end + + should "return the bytesize of String" do + Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6 + end + + should "return status code for integer" do + Rack::Utils.status_code(200).should.equal 200 + end + + should "return status code for string" do + Rack::Utils.status_code("200").should.equal 200 + end + + should "return status code for symbol" do + Rack::Utils.status_code(:ok).should.equal 200 + end +end + +describe Rack::Utils, "byte_range" do + should "ignore missing or syntactically invalid byte ranges" do + Rack::Utils.byte_ranges({},500).should.equal nil + Rack::Utils.byte_ranges({"HTTP_RANGE" => "foobar"},500).should.equal nil + Rack::Utils.byte_ranges({"HTTP_RANGE" => "furlongs=123-456"},500).should.equal nil + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes="},500).should.equal nil + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-"},500).should.equal nil + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123,456"},500).should.equal nil + # A range of non-positive length is syntactically invalid and ignored: + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-123"},500).should.equal nil + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-455"},500).should.equal nil + end + + should "parse simple byte ranges" do + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},500).should.equal [(123..456)] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-"},500).should.equal [(123..499)] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},500).should.equal [(400..499)] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},500).should.equal [(0..0)] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=499-499"},500).should.equal [(499..499)] + end + + should "truncate byte ranges" do + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-999"},500).should.equal [(123..499)] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=600-999"},500).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-999"},500).should.equal [(0..499)] + end + + should "ignore unsatisfiable byte ranges" do + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-501"},500).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-"},500).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=999-"},500).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},500).should.equal [] + end + + should "handle byte ranges of empty files" do + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},0).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-"},0).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},0).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},0).should.equal [] + Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},0).should.equal [] + end +end + +describe Rack::Utils::HeaderHash do + should "retain header case" do + h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") + h['ETag'] = 'Boo!' + h.to_hash.should.equal "Content-MD5" => "d5ff4e2a0 ...", "ETag" => 'Boo!' + end + + should "check existence of keys case insensitively" do + h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") + h.should.include 'content-md5' + h.should.not.include 'ETag' + end + + should "merge case-insensitively" do + h = Rack::Utils::HeaderHash.new("ETag" => 'HELLO', "content-length" => '123') + merged = h.merge("Etag" => 'WORLD', 'Content-Length' => '321', "Foo" => 'BAR') + merged.should.equal "Etag"=>'WORLD', "Content-Length"=>'321', "Foo"=>'BAR' + end + + should "overwrite case insensitively and assume the new key's case" do + h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz") + h["foo-bar"] = "bizzle" + h["FOO-BAR"].should.equal "bizzle" + h.length.should.equal 1 + h.to_hash.should.equal "foo-bar" => "bizzle" + end + + should "be converted to real Hash" do + h = Rack::Utils::HeaderHash.new("foo" => "bar") + h.to_hash.should.be.instance_of Hash + end + + should "convert Array values to Strings when converting to Hash" do + h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"]) + h.to_hash.should.equal({ "foo" => "bar\nbaz" }) + end + + should "replace hashes correctly" do + h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz") + j = {"foo" => "bar"} + h.replace(j) + h["foo"].should.equal "bar" + end + + should "be able to delete the given key case-sensitively" do + h = Rack::Utils::HeaderHash.new("foo" => "bar") + h.delete("foo") + h["foo"].should.be.nil + h["FOO"].should.be.nil + end + + should "be able to delete the given key case-insensitively" do + h = Rack::Utils::HeaderHash.new("foo" => "bar") + h.delete("FOO") + h["foo"].should.be.nil + h["FOO"].should.be.nil + end + + should "return the deleted value when #delete is called on an existing key" do + h = Rack::Utils::HeaderHash.new("foo" => "bar") + h.delete("Foo").should.equal("bar") + end + + should "return nil when #delete is called on a non-existant key" do + h = Rack::Utils::HeaderHash.new("foo" => "bar") + h.delete("Hello").should.be.nil + end + + should "avoid unnecessary object creation if possible" do + a = Rack::Utils::HeaderHash.new("foo" => "bar") + b = Rack::Utils::HeaderHash.new(a) + b.object_id.should.equal(a.object_id) + b.should.equal(a) + end + + should "convert Array values to Strings when responding to #each" do + h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"]) + h.each do |k,v| + k.should.equal("foo") + v.should.equal("bar\nbaz") + end + end + + should "not create headers out of thin air" do + h = Rack::Utils::HeaderHash.new + h['foo'] + h['foo'].should.be.nil + h.should.not.include 'foo' + end +end + +describe Rack::Utils::Context do + class ContextTest + attr_reader :app + def initialize app; @app=app; end + def call env; context env; end + def context env, app=@app; app.call(env); end + end + test_target1 = proc{|e| e.to_s+' world' } + test_target2 = proc{|e| e.to_i+2 } + test_target3 = proc{|e| nil } + test_target4 = proc{|e| [200,{'Content-Type'=>'text/plain', 'Content-Length'=>'0'},['']] } + test_app = ContextTest.new test_target4 + + should "set context correctly" do + test_app.app.should.equal test_target4 + c1 = Rack::Utils::Context.new(test_app, test_target1) + c1.for.should.equal test_app + c1.app.should.equal test_target1 + c2 = Rack::Utils::Context.new(test_app, test_target2) + c2.for.should.equal test_app + c2.app.should.equal test_target2 + end + + should "alter app on recontexting" do + c1 = Rack::Utils::Context.new(test_app, test_target1) + c2 = c1.recontext(test_target2) + c2.for.should.equal test_app + c2.app.should.equal test_target2 + c3 = c2.recontext(test_target3) + c3.for.should.equal test_app + c3.app.should.equal test_target3 + end + + should "run different apps" do + c1 = Rack::Utils::Context.new test_app, test_target1 + c2 = c1.recontext test_target2 + c3 = c2.recontext test_target3 + c4 = c3.recontext test_target4 + a4 = Rack::Lint.new c4 + a5 = Rack::Lint.new test_app + r1 = c1.call('hello') + r1.should.equal 'hello world' + r2 = c2.call(2) + r2.should.equal 4 + r3 = c3.call(:misc_symbol) + r3.should.be.nil + r4 = Rack::MockRequest.new(a4).get('/') + r4.status.should.equal 200 + r5 = Rack::MockRequest.new(a5).get('/') + r5.status.should.equal 200 + r4.body.should.equal r5.body + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_webrick.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_webrick.rb new file mode 100644 index 0000000..e3af233 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/spec_webrick.rb @@ -0,0 +1,141 @@ +require 'rack/mock' +require File.expand_path('../testrequest', __FILE__) + +Thread.abort_on_exception = true + +describe Rack::Handler::WEBrick do + extend TestRequest::Helpers + + @server = WEBrick::HTTPServer.new(:Host => @host='0.0.0.0', + :Port => @port=9202, + :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN), + :AccessLog => []) + @server.mount "/test", Rack::Handler::WEBrick, + Rack::Lint.new(TestRequest.new) + Thread.new { @server.start } + trap(:INT) { @server.shutdown } + + should "respond" do + lambda { + GET("/test") + }.should.not.raise + end + + should "be a WEBrick" do + GET("/test") + status.should.equal 200 + response["SERVER_SOFTWARE"].should =~ /WEBrick/ + response["HTTP_VERSION"].should.equal "HTTP/1.1" + response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" + response["SERVER_PORT"].should.equal "9202" + response["SERVER_NAME"].should.equal "0.0.0.0" + end + + should "have rack headers" do + GET("/test") + response["rack.version"].should.equal [1,1] + response["rack.multithread"].should.be.true + response["rack.multiprocess"].should.be.false + response["rack.run_once"].should.be.false + end + + should "have CGI headers on GET" do + GET("/test") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test" + response["PATH_INFO"].should.be.equal "" + response["QUERY_STRING"].should.equal "" + response["test.postdata"].should.equal "" + + GET("/test/foo?quux=1") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test/foo" + response["PATH_INFO"].should.equal "/foo" + response["QUERY_STRING"].should.equal "quux=1" + + GET("/test/foo%25encoding?quux=1") + response["REQUEST_METHOD"].should.equal "GET" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test/foo%25encoding" + response["PATH_INFO"].should.equal "/foo%25encoding" + response["QUERY_STRING"].should.equal "quux=1" + end + + should "have CGI headers on POST" do + POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'}) + status.should.equal 200 + response["REQUEST_METHOD"].should.equal "POST" + response["SCRIPT_NAME"].should.equal "/test" + response["REQUEST_PATH"].should.equal "/test" + response["PATH_INFO"].should.equal "" + response["QUERY_STRING"].should.equal "" + response["HTTP_X_TEST_HEADER"].should.equal "42" + response["test.postdata"].should.equal "rack-form-data=23" + end + + should "support HTTP auth" do + GET("/test", {:user => "ruth", :passwd => "secret"}) + response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ=" + end + + should "set status" do + GET("/test?secret") + status.should.equal 403 + response["rack.url_scheme"].should.equal "http" + end + + should "correctly set cookies" do + @server.mount "/cookie-test", Rack::Handler::WEBrick, + Rack::Lint.new(lambda { |req| + res = Rack::Response.new + res.set_cookie "one", "1" + res.set_cookie "two", "2" + res.finish + }) + + Net::HTTP.start(@host, @port) { |http| + res = http.get("/cookie-test") + res.code.to_i.should.equal 200 + res.get_fields("set-cookie").should.equal ["one=1", "two=2"] + } + end + + should "provide a .run" do + block_ran = false + catch(:done) { + Rack::Handler::WEBrick.run(lambda {}, + {:Port => 9210, + :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN), + :AccessLog => []}) { |server| + block_ran = true + server.should.be.kind_of WEBrick::HTTPServer + @s = server + throw :done + } + } + block_ran.should.be.true + @s.shutdown + end + + should "return repeated headers" do + @server.mount "/headers", Rack::Handler::WEBrick, + Rack::Lint.new(lambda { |req| + [ + 401, + { "Content-Type" => "text/plain", + "WWW-Authenticate" => "Bar realm=X\nBaz realm=Y" }, + [""] + ] + }) + + Net::HTTP.start(@host, @port) { |http| + res = http.get("/headers") + res.code.to_i.should.equal 401 + res["www-authenticate"].should.equal "Bar realm=X, Baz realm=Y" + } + end + + @server.shutdown +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/testrequest.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/testrequest.rb new file mode 100644 index 0000000..c5e339a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/testrequest.rb @@ -0,0 +1,78 @@ +require 'yaml' +require 'net/http' +require 'rack/lint' + +class TestRequest + NOSERIALIZE = [Method, Proc, Rack::Lint::InputWrapper] + + def call(env) + status = env["QUERY_STRING"] =~ /secret/ ? 403 : 200 + env["test.postdata"] = env["rack.input"].read + minienv = env.dup + # This may in the future want to replace with a dummy value instead. + minienv.delete_if { |k,v| NOSERIALIZE.any? { |c| v.kind_of?(c) } } + body = minienv.to_yaml + size = body.respond_to?(:bytesize) ? body.bytesize : body.size + [status, {"Content-Type" => "text/yaml", "Content-Length" => size.to_s}, [body]] + end + + module Helpers + attr_reader :status, :response + + ROOT = File.expand_path(File.dirname(__FILE__) + "/..") + ENV["RUBYOPT"] = "-I#{ROOT}/lib -rubygems" + + def root + ROOT + end + + def rackup + "#{ROOT}/bin/rackup" + end + + def GET(path, header={}) + Net::HTTP.start(@host, @port) { |http| + user = header.delete(:user) + passwd = header.delete(:passwd) + + get = Net::HTTP::Get.new(path, header) + get.basic_auth user, passwd if user && passwd + http.request(get) { |response| + @status = response.code.to_i + begin + @response = YAML.load(response.body) + rescue TypeError, ArgumentError + @response = nil + end + } + } + end + + def POST(path, formdata={}, header={}) + Net::HTTP.start(@host, @port) { |http| + user = header.delete(:user) + passwd = header.delete(:passwd) + + post = Net::HTTP::Post.new(path, header) + post.form_data = formdata + post.basic_auth user, passwd if user && passwd + http.request(post) { |response| + @status = response.code.to_i + @response = YAML.load(response.body) + } + } + end + end +end + +class StreamingRequest + def self.call(env) + [200, {"Content-Type" => "text/plain"}, new] + end + + def each + yield "hello there!\n" + sleep 5 + yield "that is all.\n" + end +end diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/unregistered_handler/rack/handler/unregistered.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/unregistered_handler/rack/handler/unregistered.rb new file mode 100644 index 0000000..6dd9436 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/unregistered_handler/rack/handler/unregistered.rb @@ -0,0 +1,7 @@ +module Rack + module Handler + # this class doesn't do anything, we're just seeing if we get it. + class Unregistered + end + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-1.3.6/test/unregistered_handler/rack/handler/unregistered_long_one.rb b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/unregistered_handler/rack/handler/unregistered_long_one.rb new file mode 100644 index 0000000..1920685 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-1.3.6/test/unregistered_handler/rack/handler/unregistered_long_one.rb @@ -0,0 +1,7 @@ +module Rack + module Handler + # this class doesn't do anything, we're just seeing if we get it. + class UnregisteredLongOne + end + end +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/CHANGES b/vendor/ruby/1.9.1/gems/rack-cache-1.1/CHANGES new file mode 100644 index 0000000..ed9990a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/CHANGES @@ -0,0 +1,232 @@ +## 1.1 / September 2011 + + * Allow (INM/IMS) validation requests through to backend on miss. Makes it + possible to use validation for private / uncacheable responses. A number of + people using Rails's stale?() helper reported that their validation logic was + never kicking in. + + * Add rack env rack-cache.force-pass option to bypass rack-cache on + per request basis + + * Fix an issue with memcache namespace not being set when using the + :namespace option instead of :prefix_key. + + * Fix test failures due to MockResponse changes in recent Rack + version (issue #34) + +## 1.0.3 / August 2011 + + * Fix bug passing options to memcached and dalli + + * Document cache_key + +## 1.0.1 / April 2011 + + * Added lib/rack-cache.rb to match package name for auto-requiring machinery. + + * Fixed a number of issues caused by Rack::Cache not closing the body received + from the application. Rack::Lock and other middleware use body.close to + signal the true end of request processing so failure to call this method + can result in strange issues (e.g., + "ThreadError: deadlock; recursive locking") + + * Fixed a bug where Rack::Cache would blow up writing the rack env to the meta + store when the env contained an all uppercase key whose value wasn't + marshalable. Passenger and some other stuff write such keys apparently. + + * The test suite has moved from test-spec to bacon. This is a short term + solution to the problem of not being able to run tests under Ruby 1.9.x. + The test suite will be moved to basic Test::Unit style sometime in the + future. + +## 1.0 / December 2010 + + * Rack::Cache is 1.0 and will now maintain semantic versioning + + * Add Dalli memcache client support and removed support for the unmaintained + memcache-client library. You will need to move your apps to Dalli before + upgrading rack-cache to 1.0. + +## 0.5.3 / September 2010 + + * A matching If-Modified-Since is ignored if an If-None-Match is also provided + and doesn't match. This is in line with RFC 2616. + + * Converts string status codes to integers before returns to workaround bad + behaving rack middleware and apps. + + * Misc doc clean up. + +## 0.5.2 / September 2009 + + * Exceptions raised from the metastore are not fatal. This makes a lot of + sense in most cases because its okay for the cache to be down - it + shouldn't blow up your app. + +## 0.5.1 / June 2009 + + * Added support for memcached clusters and other advanced + configuration provided by the memcache-client and memcached + libraries. The "metastore" and "entitystore" options can now be + set to a MemCache object or Memcached object: + + memcache = MemCache.new(['127.1.1.1', '127.1.1.2'], :namespace => "/foo") + use Rack::Cache, + :metastore => memcache, + :entitystore => memcache + + * Fix "memcached://" metastore URL handling. The "memcached" variation + blew up, the "memcache" version was fine. + +## 0.5.0 / May 2009 + + * Added meta and entity store implementations based on the + memcache-client library. These are the default unless the memcached + library has already been required. + + * The "allow_reload" and "allow_revalidate" options now default to + false instead of true. This means we break with RFC 2616 out of + the box but this is the expected configuration in a huge majority + of gateway cache scenarios. See the docs on configuration + options for more information on these options: + http://tomayko.com/src/rack-cache/configuration + + * Added Google AppEngine memcache entity store and metastore + implementations. To use GAE's memcache with rack-cache, set the + "metastore" and "entitystore" options as follows: + + use Rack::Cache, + :metastore => 'gae://cache-meta', + :entitystore => 'gae://cache-body' + + The 'cache-meta' and 'cache-body' parts are memcache namespace + prefixes and should be set to different values. + +## 0.4.0 / March 2009 + + * Ruby 1.9.1 / Rack 1.0 compatible. + + * Invalidate cache entries that match the request URL on non-GET/HEAD + requests. i.e., POST, PUT, DELETE cause matching cache entries to + be invalidated. The cache entry is validated with the backend using + a conditional GET the next time it's requested. + + * Implement "Cache-Control: max-age=N" request directive by forcing + validation when the max-age provided exceeds the age of the cache + entry. This can be disabled by setting the "allow_revalidate" option to + false. + + * Properly implement "Cache-Control: no-cache" request directive by + performing a full reload. RFC 2616 states that when "no-cache" is + present in the request, the cache MUST NOT serve a stored response even + after successful validation. This is slightly different from the + "no-cache" directive in responses, which indicates that the cache must + first validate its entry with the origin. Previously, we implemented + "no-cache" on requests by passing so no new cache entry would be stored + based on the response. Now we treat it as a forced miss and enter the + response into the cache if it's cacheable. This can be disabled by + setting the "allow_reload" option to false. + + * Assume identical semantics for the "Pragma: no-cache" request header + as the "Cache-Control: no-cache" directive described above. + + * Less crazy logging. When the verbose option is set, a single log entry + is written with a comma separated list of trace events. For example, if + the cache was stale but validated, the following log entry would be + written: "cache: stale, valid, store". When the verbose option is false, + no logging occurs. + + * Added "X-Rack-Cache" response header with the same comma separated trace + value as described above. This gives some visibility into how the cache + processed the request. + + * Add support for canonicalized cache keys, as well as custom cache key + generators, which are specified in the options as :cache_key as either + any object that has a call() or as a block. Cache key generators get + passed a request object and return a cache key string. + +## 0.3.0 / December 2008 + + * Add support for public and private cache control directives. Responses + marked as explicitly public are cached even when the request includes + an Authorization or Cookie header. Responses marked as explicitly private + are considered uncacheable. + + * Added a "private_headers" option that dictates which request headers + trigger default "private" cache control processing. By default, the + Cookie and Authorization headers are included. Headers may be added or + removed as necessary to change the default private logic. + + * Adhere to must-revalidate/proxy-revalidate cache control directives by + not assigning the default_ttl to responses that don't include freshness + information. This should let us begin using default_ttl more liberally + since we can control it using the must-revalidate/proxy-revalidate directives. + + * Use the s-maxage Cache-Control value in preference to max-age when + present. The ttl= method now sets the s-maxage value instead of max-age. + Code that used ttl= to control freshness at the client needs to change + to set the max-age directive explicitly. + + * Enable support for X-Sendfile middleware by responding to #to_path on + bodies served from disk storage. Adding the Rack::Sendfile component + upstream from Rack::Cache will result in cached bodies being served + directly by the web server (instead of being read in Ruby). + + * BUG: MetaStore hits but EntityStore misses. This would 500 previously; now + we detect it and act as if the MetaStore missed as well. + + * Implement low level #purge method on all concrete entity store + classes -- removes the entity body corresponding to the SHA1 key + provided and returns nil. + + * Basically sane handling of HEAD requests. A HEAD request is never passed + through to the backend except when transitioning with pass!. This means + that the cache responds to HEAD requests without invoking the backend at + all when the cached entry is fresh. When no cache entry exists, or the + cached entry is stale and can be validated, the backend is invoked with + a GET request and the HEAD is handled right before the response + is delivered upstream. + + * BUG: The Age response header was not being set properly when a stale + entry was validated. This would result in Age values that exceeded + the freshness lifetime in responses. + + * BUG: A cached entry in a heap meta store could be unintentionally + modified by request processing since the cached objects were being + returned directly. The result was typically missing/incorrect header + values (e.g., missing Content-Type header). [dkubb] + + * BUG: 304 responses should not include entity headers (especially + Content-Length). This is causing Safari/WebKit weirdness on 304 + responses. + + * BUG: The If-None-Match header was being ignored, causing the cache + to send 200 responses to matching conditional GET requests. + +## 0.2.0 / 2008-10-24 / Initial Release + + * Document events and transitions in `rack/cache/config/default.rb` + * Basic logging support (`trace`, `warn`, `info`, `error` from within Context) + * EntityStore: store entity bodies keyed by SHA + * MetaStore: store response headers keyed by URL + * Last-Modified/ETag validation + * Vary support + * Implement error! transition + * New Rack::Cache::Core + * memcached meta and entity store implementations + * URI based storage configuration + * Read options from Rack env if present (rack-cache.XXX keys) + * `object` is now `entry` + * Documentation framework and website + * Document storage areas and implementations + * Document configuration/events + +## 0.1.0 / 2008-07-21 / Proof of concept (unreleased) + + * Basic core with event support + * `#import` method for bringing in config files + * Freshness based expiration + * RFC 2616 If-Modified-Since based validation + * A horribly shitty storage back-end (Hash in mem) + * Don't cache hop-by-hop headers: Connection, Keep-Alive, Proxy-Authenticate, + Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/COPYING b/vendor/ruby/1.9.1/gems/rack-cache-1.1/COPYING new file mode 100644 index 0000000..acd3e49 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/COPYING @@ -0,0 +1,18 @@ +Copyright (c) 2008 Ryan Tomayko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/Gemfile b/vendor/ruby/1.9.1/gems/rack-cache-1.1/Gemfile new file mode 100644 index 0000000..e45e65f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/Gemfile @@ -0,0 +1,2 @@ +source :rubygems +gemspec diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/Gemfile.lock b/vendor/ruby/1.9.1/gems/rack-cache-1.1/Gemfile.lock new file mode 100644 index 0000000..1fa3280 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/Gemfile.lock @@ -0,0 +1,22 @@ +PATH + remote: . + specs: + rack-cache (1.0.3) + rack (>= 0.4) + +GEM + remote: http://rubygems.org/ + specs: + bacon (1.1.0) + dalli (1.0.5) + memcached (1.3) + rack (1.3.2) + +PLATFORMS + ruby + +DEPENDENCIES + bacon + dalli + memcached + rack-cache! diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/README b/vendor/ruby/1.9.1/gems/rack-cache-1.1/README new file mode 100644 index 0000000..2faf0be --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/README @@ -0,0 +1,126 @@ +Rack::Cache +=========== + +Rack::Cache is suitable as a quick drop-in component to enable HTTP caching for +Rack-based applications that produce freshness (Expires, Cache-Control) and/or +validation (Last-Modified, ETag) information: + + * Standards-based (RFC 2616) + * Freshness/expiration based caching + * Validation (If-Modified-Since / If-None-Match) + * Vary support + * Cache-Control: public, private, max-age, s-maxage, must-revalidate, + and proxy-revalidate. + * Portable: 100% Ruby / works with any Rack-enabled framework + * Disk, memcached, and heap memory storage backends + +For more information about Rack::Cache features and usage, see: + +http://tomayko.com/src/rack-cache/ + +Rack::Cache is not overly optimized for performance. The main goal of the +project is to provide a portable, easy-to-configure, and standards-based +caching solution for small to medium sized deployments. More sophisticated / +high-performance caching systems (e.g., Varnish, Squid, httpd/mod-cache) may be +more appropriate for large deployments with significant throughput requirements. + +Installation +------------ + +From Gem: + + $ sudo gem install rack-cache + +With a local working copy: + + $ git clone git://github.com/rtomayko/rack-cache.git + $ rake package && sudo rake install + +Basic Usage +----------- + +Rack::Cache is implemented as a piece of Rack middleware and can be used with +any Rack-based application. If your application includes a rackup (`.ru`) file +or uses Rack::Builder to construct the application pipeline, simply require +and use as follows: + + require 'rack/cache' + + use Rack::Cache, + :metastore => 'file:/var/cache/rack/meta', + :entitystore => 'file:/var/cache/rack/body', + :verbose => true + + run app + +Assuming you've designed your backend application to take advantage of HTTP's +caching features, no further code or configuration is required for basic +caching. + +Using with Rails +---------------- + +Add this to your `config/environment.rb`: + + config.middleware.use Rack::Cache, + :verbose => true, + :metastore => 'file:/var/cache/rack/meta', + :entitystore => 'file:/var/cache/rack/body' + +You should now see `Rack::Cache` listed in the middleware pipeline: + + rake middleware + +See the following for more information: + + http://snippets.aktagon.com/snippets/302 + +Using with Dalli +---------------- + +Dalli is a high performance memcached client for Ruby. +More information at: https://github.com/mperham/dalli + + require 'dalli' + require 'rack/cache' + + use Rack::Cache, + :verbose => true, + :metastore => "memcached://localhost:11211/meta", + :entitystore => "memcached://localhost:11211/body" + + run app + +Links +----- + +Documentation: + http://tomayko.com/src/rack-cache/ + +Mailing List: + http://groups.google.com/group/rack-cache + +GitHub: + http://github.com/rtomayko/rack-cache/ + +License +------- + +Copyright (c) 2008 Ryan Tomayko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/Rakefile b/vendor/ruby/1.9.1/gems/rack-cache-1.1/Rakefile new file mode 100644 index 0000000..3e7bd5d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/Rakefile @@ -0,0 +1,139 @@ +require 'rake/clean' + +task :default => [:setup, :test] + +CLEAN.include %w[coverage/ doc/api tags] +CLOBBER.include %w[dist] + +desc "Install gem dependencies" +task :setup do + sh "bundle check >/dev/null || bundle install", :verbose => false +end + +# SPECS ===================================================================== + +desc 'Run specs with unit test style output' +task :test => FileList['test/*_test.rb'] do |t| + suite = t.prerequisites + sh "bacon -q -I.:lib:test #{suite.join(' ')}", :verbose => false +end + +desc 'Run specs with story style output' +task :spec => FileList['test/*_test.rb'] do |t| + suite = t.prerequisites + sh "bacon -I.:lib:test #{suite.join(' ')}", :verbose => false +end + +desc 'Generate test coverage report' +task :rcov do + sh "rcov -I.:lib:test test/*_test.rb" +end + +# DOC ======================================================================= +desc 'Build all documentation' +task :doc => %w[doc:api doc:markdown] + +# requires the hanna gem: +# gem install mislav-hanna --source=http://gems.github.com +desc 'Build API documentation (doc/api)' +task 'doc:api' => 'doc/api/index.html' +file 'doc/api/index.html' => FileList['lib/**/*.rb'] do |f| + rm_rf 'doc/api' + sh((<<-SH).gsub(/[\s\n]+/, ' ').strip) + hanna + --op doc/api + --promiscuous + --charset utf8 + --fmt html + --inline-source + --line-numbers + --accessor option_accessor=RW + --main Rack::Cache + --title 'Rack::Cache API Documentation' + #{f.prerequisites.join(' ')} + SH +end +CLEAN.include 'doc/api' + +desc 'Build markdown documentation files' +task 'doc:markdown' +FileList['doc/*.markdown'].each do |source| + dest = "doc/#{File.basename(source, '.markdown')}.html" + file dest => [source, 'doc/layout.html.erb'] do |f| + puts "markdown: #{source} -> #{dest}" if verbose + require 'erb' unless defined? ERB + require 'rdiscount' unless defined? RDiscount + template = File.read(source) + content = Markdown.new(ERB.new(template, 0, "%<>").result(binding), :smart).to_html + title = content.match("

        (.*)

        ")[1] rescue '' + layout = ERB.new(File.read("doc/layout.html.erb"), 0, "%<>") + output = layout.result(binding) + File.open(dest, 'w') { |io| io.write(output) } + end + task 'doc:markdown' => dest + CLEAN.include dest +end + +desc 'Publish documentation' +task 'doc:publish' => :doc do + sh 'rsync -avz doc/ gus@tomayko.com:/src/rack-cache' +end + +desc 'Start the documentation development server (requires thin)' +task 'doc:server' do + sh 'cd doc && thin --rackup server.ru --port 3035 start' +end + +# PACKAGING ================================================================= + +if defined?(Gem) + # load gemspec + $spec = eval(File.read('rack-cache.gemspec')) + + def package(ext='') + "dist/rack-cache-#{$spec.version}" + ext + end + + desc 'Build packages' + task :package => %w[.gem .tar.gz].map {|e| package(e)} + + desc 'Build and install as local gem' + task :install => package('.gem') do + sh "gem install #{package('.gem')}" + end + + directory 'dist/' + + file package('.gem') => %w[dist/ rack-cache.gemspec] + $spec.files do |f| + sh "gem build rack-cache.gemspec" + mv File.basename(f.name), f.name + end + + file package('.tar.gz') => %w[dist/] + $spec.files do |f| + sh "git archive --format=tar HEAD | gzip > #{f.name}" + end + + desc 'Upload gem to gemcutter.org' + task 'release' => [package('.gem')] do |t| + sh "gem push #{package('.gem')}" + end +end + +# GEMSPEC =================================================================== + +file 'rack-cache.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f| + # read spec file and split out manifest section + spec = File.read(f.name) + parts = spec.split(" # = MANIFEST =\n") + fail 'bad spec' if parts.length != 3 + # determine file list from git ls-files + files = `git ls-files`. + split("\n").sort.reject{ |file| file =~ /^\./ }. + map{ |file| " #{file}" }.join("\n") + # piece file back together and write... + parts[1] = " s.files = %w[\n#{files}\n ]\n" + spec = parts.join(" # = MANIFEST =\n") + spec.sub!(/s.date = '.*'/, "s.date = '#{Time.now.strftime("%Y-%m-%d")}'") + File.open(f.name, 'w') { |io| io.write(spec) } + puts "updated #{f.name}" +end diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/TODO b/vendor/ruby/1.9.1/gems/rack-cache-1.1/TODO new file mode 100644 index 0000000..fd6690f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/TODO @@ -0,0 +1,27 @@ +## 0.5 + + - Document allow_revalidate and allow_reload options. + - Support multiple memcache servers. + - Purge/invalidate everything + - Explicit expiration/invalidation based on response headers or via an + object interface passed in the rack env. + - Sample apps: Rack, Rails, Sinatra, Merb, etc. + - Move old breakers.rb configuration file into rack-contrib as a + middleware component. + +## Backlog + + - Use Bacon instead of test/spec + - Fast path pass processing. We do a lot more than necessary just to determine + that the response should be passed through untouched. + - Invalidate at the URI of the Location or Content-Location response header + on POST, PUT, or DELETE that results in a redirect. + - Maximum size of cached entity + - Last-Modified factor: requests that have a Last-Modified header but no Expires + header have a TTL assigned based on the last modified age of the response: + TTL = (Age * Factor), or, 1h = (10h * 0.1) + - Consider implementing ESI (http://www.w3.org/TR/esi-lang). This should + probably be implemented as a separate middleware component. + - stale-while-revalidate + - Serve cached copies when down (see: stale-if-error) - e.g., database + connection drops and the cache takes over what it can. diff --git a/vendor/ruby/1.9.1/gems/rack-cache-1.1/doc/configuration.markdown b/vendor/ruby/1.9.1/gems/rack-cache-1.1/doc/configuration.markdown new file mode 100644 index 0000000..0925561 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/rack-cache-1.1/doc/configuration.markdown @@ -0,0 +1,127 @@ +Configuration +============= + +__Rack::Cache__ includes a configuration system that can be used to specify +fairly sophisticated cache policy on a global or per-request basis. + + + +Setting Cache Options +--------------------- + +Cache options can be set when the __Rack::Cache__ object is created, +or by setting a `rack-cache.