javascript_features 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ require 'jsmin'
2
+
3
+ module JavascriptFeatures
4
+ module Compiler
5
+ def self.compile(options = {})
6
+ defaults = {:minify => true, :package => 'main'}
7
+ options = defaults.merge(options)
8
+
9
+ files = files_for_package(options[:package])
10
+ compiled = files.map{|file| File.read(file) }.join("\n")
11
+ minified = JSMin.minify(compiled) if options[:minify]
12
+
13
+ minified || compiled
14
+ end
15
+
16
+ def self.package_modified_time(package = 'main')
17
+ files_for_package(package).map{|f| File.new(f).mtime }.max
18
+ end
19
+
20
+ private
21
+ def self.files_for_package(package)
22
+ lib_files = Dir.glob(Rails.root + 'public/javascripts/lib/**/*.js')
23
+ init_files = [File.join(File.dirname(__FILE__), *%w[ .. .. assets init.js ])]
24
+ feature_files = Dir.glob(Rails.root + "public/javascripts/#{package}/**/*.js")
25
+ lib_files + init_files + feature_files
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ module JavascriptFeatures
2
+ module Helper
3
+
4
+ def self.included(controller)
5
+ controller.helper_method :use_javascript_for, :use_javascript_for?, :javascript_feature_classes, :include_javascript_features if controller.respond_to? :helper_method
6
+ end
7
+
8
+ def use_javascript_for(*features)
9
+ @javascript_features ||= []
10
+ @javascript_features += features.map{|f| f.to_s.downcase }
11
+ response.headers['X-JavascriptFeatures-Init'] = @javascript_features.uniq.join(' ') if request && request.xhr?
12
+ end
13
+
14
+ def use_javascript_for?(feature)
15
+ @javascript_features.include?(feature.to_s.downcase)
16
+ end
17
+
18
+ def javascript_feature_classes
19
+ (@javascript_features || []).uniq.map{ |feature| "with-js-#{feature}" }.join(" ")
20
+ end
21
+
22
+ def include_javascript_features(package = 'main')
23
+ query = Compiler.package_modified_time(package).to_i
24
+ tag = %Q{<script type="text/javascript" src="/javascripts/packaged/#{package}.js?#{query}"></script>}
25
+ if tag.respond_to?(:html_safe)
26
+ tag.html_safe
27
+ else
28
+ tag
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ module JavascriptFeatures
2
+ class TestCase
3
+ class Servlet < ::WEBrick::HTTPServlet::AbstractServlet
4
+ def initialize(server, pages)
5
+ super server
6
+ @pages = pages
7
+ end
8
+
9
+ def service(req, res)
10
+ page = @pages[req.path]
11
+ if page
12
+ res.status = 200
13
+ res['Content-Type'] = 'text/html'
14
+ if page.is_a?(Hash)
15
+ page[:headers].each{ |k,v| res[k] = v }
16
+ res.body = page[:body]
17
+ else
18
+ res.body = page
19
+ end
20
+ elsif req.path =~ %r[^/javascripts/packaged/([^/]+).js$]
21
+ res.status = 200
22
+ res['Content-Type'] = 'text/javascript'
23
+ res.body = JavascriptFeatures::Compiler.compile(:package => $1)
24
+ else
25
+ res.status = 404
26
+ res['Content-Type'] = 'text/plain'
27
+ res.body = 'Not found'
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,91 @@
1
+ require 'active_support/test_case'
2
+ require 'harmony'
3
+
4
+ module JavascriptFeatures
5
+ class TestCase < ::ActiveSupport::TestCase
6
+ extend JavascriptFeatures::Helper
7
+
8
+ autoload :Servlet, 'javascript_features/test_case/servlet'
9
+
10
+ class << self
11
+ def request
12
+ nil
13
+ end
14
+
15
+ def uses_feature_package(package)
16
+ @feature_package = package
17
+ end
18
+
19
+ def feature_package
20
+ @feature_package ||= 'main'
21
+ end
22
+
23
+ def tests_feature(*names)
24
+ @feature_names = names
25
+ end
26
+
27
+ def feature_names
28
+ @feature_names ||= [self.name.downcase.sub(/test$/, '')]
29
+ end
30
+
31
+ def stubs_http_request(url, options)
32
+ @server_pages = server_pages.merge(url => options)
33
+ end
34
+
35
+ def server_pages
36
+ @server_pages ||= {}
37
+ end
38
+
39
+ def uses_html(&block)
40
+ define_method(:setup) do
41
+ self.class.feature_names.each{ |f| self.class.use_javascript_for f }
42
+ @html = yield.strip
43
+
44
+ server_config = {:BindAddress => '0.0.0.0', :Port => 8076, :AccessLog => [], :Logger => WEBrick::Log::new('/dev/null', 7)}
45
+ @server = ::WEBrick::HTTPServer.new(server_config)
46
+ pages = self.class.server_pages.merge(
47
+ '/index.html' => @html,
48
+ '/jquery.js' => File.read(File.expand_path('../../../assets/jquery.js', __FILE__))
49
+ )
50
+ @server.mount('/', JavascriptFeatures::TestCase::Servlet, pages)
51
+ Thread.new{ @server.start }
52
+
53
+ @page = Harmony::Page.fetch("http://#{server_config[:BindAddress]}:#{server_config[:Port]}/index.html")
54
+ Harmony::Page::Window::BASE_RUNTIME.wait
55
+ end
56
+
57
+ define_method(:teardown) do
58
+ @server.shutdown
59
+ end
60
+ end
61
+
62
+ def uses_html_body
63
+ uses_html do
64
+ %%
65
+ <!DOCTYPE html>
66
+ <html lang="en">
67
+ <head>
68
+ <title>Test page</title>
69
+ </head>
70
+ <body class="#{javascript_feature_classes}">
71
+ #{yield.strip}
72
+
73
+ <script src='/jquery.js'></script>
74
+ #{include_javascript_features(feature_package)}
75
+ </body>
76
+ </html>
77
+ %
78
+ end
79
+ end
80
+ end
81
+
82
+ def execute_js(*args)
83
+ @page.execute_js(*args)
84
+ end
85
+
86
+ def assert_selector_count(expected_count, selector)
87
+ real_count = execute_js("jQuery(#{selector.to_json}).length")
88
+ assert_equal expected_count, real_count, "Expected #{expected_count} elements matching selector #{selector}, found #{real_count}"
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,7 @@
1
+ module JavascriptFeatures
2
+ autoload :Compiler, 'javascript_features/compiler'
3
+ autoload :Helper, 'javascript_features/helper'
4
+ autoload :TestCase, 'javascript_features/test_case'
5
+ end
6
+
7
+ ActionController::Base.send(:include, JavascriptFeatures::Helper) if defined?(ActionController)
@@ -0,0 +1,48 @@
1
+ require 'javascript_features'
2
+
3
+ module Rack
4
+ class JavascriptFeatures
5
+
6
+ DEFAULT_OPTIONS = {:minify => true}
7
+
8
+ def initialize(app, options = {})
9
+ @app = app
10
+ @options = DEFAULT_OPTIONS.merge(options)
11
+ end
12
+
13
+ def call(env)
14
+ request = Rack::Request.new(env)
15
+
16
+ if package = package_for_path(request.path)
17
+ etag = package_etag(package)
18
+ if etag == env['HTTP_IF_NONE_MATCH']
19
+ [304, {}, []]
20
+ else
21
+ javascript = package_javascript(package)
22
+ [200, {"Content-Type" => "text/javascript", "Cache-Control" => "private", "ETag" => etag}, [javascript]]
23
+ end
24
+ else
25
+ @app.call(env)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def package_for_path(path)
32
+ relevant_url = path =~ %r{javascripts/packaged/([^/]+)\.js}
33
+ package_name = relevant_url && $1
34
+ real_package = package_name && ::File.exists?(::File.join(Rails.root, 'public', 'javascripts', package_name))
35
+ real_package && package_name
36
+ end
37
+
38
+ def package_etag(package_name)
39
+ mtime = ::JavascriptFeatures::Compiler.package_modified_time(package_name)
40
+ etag = Digest::MD5.hexdigest("#{package_name}/#{mtime.to_i}")
41
+ end
42
+
43
+ def package_javascript(package_name)
44
+ ::JavascriptFeatures::Compiler.compile(:package => package_name, :minify => @options[:minify])
45
+ end
46
+
47
+ end
48
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'javascript_features'
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'jsmin'
3
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
4
+
5
+ class CompilerTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ common_files = [
9
+ File.join(Rails.root, *%w[ public javascripts lib jquery_plugin.js ]),
10
+ File.join(File.dirname(__FILE__), *%w[ .. assets init.js ])
11
+ ]
12
+
13
+ @main_files = common_files + [ File.join(Rails.root, *%w[ public javascripts main my_feature.js ]) ]
14
+ @alternative_files = common_files + [ File.join(Rails.root, *%w[ public javascripts alternative alternative.js ]) ]
15
+ end
16
+
17
+ context 'compiling the main JavaScript package' do
18
+ should 'concatenate the relevant files in the correct order and minify the result' do
19
+ assert_equal JSMin.minify(@main_files.map{|f| File.read(f) }.join("\n")), JavascriptFeatures::Compiler.compile
20
+ end
21
+
22
+ should 'optionally disable minification' do
23
+ assert_equal @main_files.map{|f| File.read(f) }.join("\n"), JavascriptFeatures::Compiler.compile(:minify => false)
24
+ end
25
+ end
26
+
27
+ context 'compiling the alternative JavaScript package' do
28
+ should 'take feature files from the /alternative directory instead of /main' do
29
+ assert_equal JSMin.minify(@alternative_files.map{|f| File.read(f) }.join("\n")), JavascriptFeatures::Compiler.compile(:package => 'alternative')
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,5 @@
1
+ Features.alternative = {
2
+ init: function() {
3
+ alert("Hello, world");
4
+ }
5
+ };
@@ -0,0 +1,7 @@
1
+ Features.disabled_feature = {
2
+ init: function() {
3
+ var div = document.createElement("div");
4
+ div.className = "disabled_feature";
5
+ document.body.appendChild(div);
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ Features.enabled_feature = {
2
+ init: function() {
3
+ var div = document.createElement("div");
4
+ div.className = "enabled_feature";
5
+ document.body.appendChild(div);
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ Features.global_feature = {
2
+ global_init: function() {
3
+ var div = document.createElement("div");
4
+ div.className = "global_feature";
5
+ document.body.appendChild(div);
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ jQuery.plugin = {};
@@ -0,0 +1,5 @@
1
+ Features.MyFeature = {
2
+ init: function($) {
3
+ alert("Initialise my feature!");
4
+ }
5
+ };
@@ -0,0 +1,5 @@
1
+ Features.global_load = {
2
+ global_init: function(context) {
3
+ context.find(".xhr-response").append("<span class=\"touched-by-global-init\"></span>");
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ Features.load = {
2
+ init: function(context) {
3
+ context.find(".xhr-response").addClass("touched-by-load");
4
+ }
5
+ }
@@ -0,0 +1,11 @@
1
+ Features.xhr = {
2
+ init: function() {
3
+ var xhr = jQuery.ajax({
4
+ url: "/xhr",
5
+ context: $(".xhr-target"),
6
+ success: function(data) {
7
+ $(".xhr-target").html(data);
8
+ }
9
+ });
10
+ }
11
+ };
@@ -0,0 +1,108 @@
1
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
2
+
3
+ class HelperTest < Test::Unit::TestCase
4
+ include JavascriptFeatures::Helper
5
+
6
+ class TestRequest
7
+ def initialize(options)
8
+ @xhr = options[:xhr]
9
+ end
10
+
11
+ def xhr?
12
+ @xhr
13
+ end
14
+
15
+ def xml_http_request?
16
+ @xhr
17
+ end
18
+ end
19
+
20
+ class TestResponse
21
+ attr_accessor :headers
22
+ def initialize
23
+ @headers = {'Content-Type' => 'text/html'}
24
+ end
25
+ end
26
+
27
+ context "when a JavaScript feature is enabled during a normal request" do
28
+ setup do
29
+ self.request = TestRequest.new(:xhr => false)
30
+ self.response = TestResponse.new
31
+ use_javascript_for "something"
32
+ end
33
+
34
+ should "set the corresponding body class" do
35
+ assert_equal "with-js-something", javascript_feature_classes
36
+ end
37
+
38
+ should 'not modify the headers' do
39
+ assert_equal({'Content-Type' => 'text/html'}, response.headers)
40
+ end
41
+
42
+ should 'be able to check that it is enabled' do
43
+ assert use_javascript_for?('something')
44
+ assert !use_javascript_for?('something-else')
45
+ end
46
+ end
47
+
48
+ context 'when a JavaScript feature is enabled during an XHR request' do
49
+ setup do
50
+ self.request = TestRequest.new(:xhr => true)
51
+ self.response = TestResponse.new
52
+ use_javascript_for "something"
53
+ use_javascript_for "something_else"
54
+ end
55
+
56
+ should 'modify the headers' do
57
+ assert_equal({'Content-Type' => 'text/html', 'X-JavascriptFeatures-Init' => 'something something_else'}, response.headers)
58
+ end
59
+ end
60
+
61
+ context "when the same feature is enabled multiple times" do
62
+ setup do
63
+ use_javascript_for "something"
64
+ use_javascript_for "something-else"
65
+ use_javascript_for "something"
66
+ end
67
+ should "only include each class once" do
68
+ assert_equal "with-js-something with-js-something-else", javascript_feature_classes
69
+ end
70
+ end
71
+
72
+ context "when no features have been enabled" do
73
+ should "not produce any classes" do
74
+ assert_equal "", javascript_feature_classes
75
+ end
76
+ end
77
+
78
+ should "allow to pass several features at one call" do
79
+ use_javascript_for "something", "something-else"
80
+ assert_equal "with-js-something with-js-something-else", javascript_feature_classes
81
+ end
82
+
83
+ context 'including the packaged JavaScript' do
84
+ setup{ @script_tag = include_javascript_features }
85
+ should 'write a script tag containing the correct URL' do
86
+ assert_match %r{/javascripts/packaged/main\.js}, @script_tag
87
+ end
88
+ end
89
+
90
+ context 'including an alternative JavaScript package' do
91
+ setup{ @script_tag = include_javascript_features(:alternative) }
92
+ should 'write a script tag containing the correct URL' do
93
+ assert_match %r{/javascripts/packaged/alternative\.js}, @script_tag
94
+ end
95
+ end
96
+
97
+ context 'including the packaged JavaScript after one of the files has been modified' do
98
+ setup do
99
+ @before_modified = include_javascript_features
100
+ FileUtils.touch File.join(Rails.root, %w[ public javascripts main my_feature.js ])
101
+ @after_modified = include_javascript_features
102
+ end
103
+
104
+ should 'include different query strings to avoid caching' do
105
+ assert @before_modified != @after_modified, "Expected #{@before_modified.inspect} and #{@after_modified.inspect} to be different"
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
2
+ require 'harmony'
3
+ require 'webrick'
4
+
5
+ class JavascriptTest < JavascriptFeatures::TestCase
6
+ uses_html_body{ '<h1>Test page</h1>' }
7
+ uses_feature_package :javascript_test
8
+ tests_feature :enabled_feature
9
+
10
+ should 'initialise the enabled feature' do
11
+ assert_selector_count 1, 'div.enabled_feature'
12
+ end
13
+
14
+ should 'not initialise the disabled feature' do
15
+ assert_selector_count 0, 'div.disabled_feature'
16
+ end
17
+
18
+ should 'initialise the global feature' do
19
+ assert_selector_count 1, 'div.global_feature'
20
+ end
21
+
22
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
2
+ require 'jslint'
3
+
4
+ class JslintTest < Test::Unit::TestCase
5
+
6
+ context 'all built-in JavaScript' do
7
+ should 'pass JSLint' do
8
+ paths = File.join(File.dirname(__FILE__), '../assets/**/*.js')
9
+ exclude = File.join(File.dirname(__FILE__), '../assets/jquery.js')
10
+ JSLint::Lint.new(:paths => paths, :exclude_paths => exclude).run
11
+ end
12
+ end
13
+
14
+ end
data/test/rack_test.rb ADDED
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
2
+ require 'rack/test'
3
+ require 'rack/javascript_features'
4
+
5
+ class RackTest < Test::Unit::TestCase
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ app = lambda{|env| [200, {"Content-Type" => "text/plain"}, ["all is well"]]}
10
+ Rack::JavascriptFeatures.new(app)
11
+ end
12
+
13
+ context "when JavaScript isn't being requested" do
14
+ setup do
15
+ get '/some/other/path'
16
+ end
17
+
18
+ should 'delegate to the app' do
19
+ assert_equal 200, last_response.status
20
+ assert_equal 'all is well', last_response.body
21
+ end
22
+ end
23
+
24
+ context "when the main JavaScript package is being requested" do
25
+ setup do
26
+ get '/javascripts/packaged/main.js'
27
+ end
28
+
29
+ should 'respond with the compiled JavaScript' do
30
+ assert_equal 200, last_response.status
31
+ assert_equal JavascriptFeatures::Compiler.compile, last_response.body
32
+ end
33
+ end
34
+
35
+ context "when the main JavaScript package is being requested with a valid ETag" do
36
+ setup do
37
+ get '/javascripts/packaged/main.js'
38
+ assert_not_nil etag = last_response.headers['ETag'], 'Expected an ETag'
39
+ get '/javascripts/packaged/main.js', {}, {'HTTP_IF_NONE_MATCH' => etag}
40
+ end
41
+
42
+ should "respond with 'not modified'" do
43
+ assert_equal 304, last_response.status
44
+ end
45
+ end
46
+
47
+ context "when the main JavaScript package is being requested with a valid ETag" do
48
+ setup do
49
+ get '/javascripts/package/main.js', {}, {'HTTP_IF_NONE_MATCH' => '12345'}
50
+ end
51
+
52
+ should "respond with some JavaScript" do
53
+ assert_equal 200, last_response.status
54
+ end
55
+ end
56
+
57
+ context "when an alternative JavaScript package is being requested" do
58
+ setup do
59
+ get '/javascripts/packaged/alternative.js'
60
+ end
61
+
62
+ should 'respond with the compiled JavaScript' do
63
+ assert_equal 200, last_response.status
64
+ assert_equal JavascriptFeatures::Compiler.compile(:package => 'alternative'), last_response.body
65
+ end
66
+ end
67
+
68
+ context "when an unknown JavaScript package is being requested" do
69
+ setup do
70
+ get '/javascripts/packaged/does_not_exist.js'
71
+ end
72
+
73
+ should 'delegate to the app' do
74
+ assert_equal 200, last_response.status
75
+ assert_equal 'all is well', last_response.body
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,59 @@
1
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
2
+
3
+ class TestCaseTest < JavascriptFeatures::TestCase
4
+ uses_html_body{ '<div class="foo"></div>' }
5
+
6
+ should 'have some HTML' do
7
+ assert_not_nil @html
8
+ end
9
+
10
+ should 'include the main JS package' do
11
+ assert_match %r{<script [^>]*src="/javascripts/packaged/main\.js(\?\d+)?"}, @html
12
+ end
13
+
14
+ should 'take the enabled feature name from the class name' do
15
+ assert_match %r{<body class="with-js-testcase">}, @html
16
+ end
17
+
18
+ should 'create a Harmony::Page for the HTML' do
19
+ assert_not_nil @page
20
+ end
21
+
22
+ should 'load the JavaScript in the Harmony::Page' do
23
+ assert_equal 'object', @page.execute_js('typeof Features')
24
+ end
25
+
26
+ should 'provide a method of executing JS without knowing about the @page variable' do
27
+ assert_equal 'object', execute_js('typeof Features')
28
+ end
29
+
30
+ should 'provide a custom assertion for counting DOM nodes' do
31
+ assert_nothing_raised{ assert_selector_count(1, 'div.foo') }
32
+ assert_raises(Test::Unit::AssertionFailedError){ assert_selector_count(2, 'div.foo') }
33
+ end
34
+
35
+ end
36
+
37
+ class CustomFeatureTest < JavascriptFeatures::TestCase
38
+ uses_html_body{ '<div class="foo"></div>' }
39
+ tests_feature 'foo'
40
+
41
+ should 'use the custom feature instead of deriving the feature from the class name' do
42
+ assert_match %r{<body class="with-js-foo">}, @html
43
+ end
44
+ end
45
+
46
+ class MultipleFeatureTest < JavascriptFeatures::TestCase
47
+ uses_html_body{ '<div class="foo"></div>' }
48
+ tests_feature 'foo', 'bar', 'baz'
49
+
50
+ should 'use all of the custom features' do
51
+ ['foo', 'bar', 'baz'].each do |feature|
52
+ assert execute_js("jQuery('body').hasClass('with-js-#{feature}')")
53
+ end
54
+ end
55
+
56
+ should 'not use the feature name derived from the class name' do
57
+ assert execute_js('!jQuery("body").hasClass("with-js-mulitplefeature")')
58
+ end
59
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ require 'bundler'
4
+ Bundler.require(:default, :development)
5
+
6
+ class Test::Unit::TestCase
7
+ attr_accessor :request, :response
8
+ end
9
+
10
+ module Rails
11
+ def self.root
12
+ File.join(File.dirname(__FILE__), 'fixtures') + '/'
13
+ end
14
+
15
+ def self.backtrace_cleaner
16
+ ActiveSupport::BacktraceCleaner.new
17
+ end
18
+ end
data/test/xhr_test.rb ADDED
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), *%w[test_helper])
2
+ require 'harmony'
3
+
4
+ class XhrTest < JavascriptFeatures::TestCase
5
+
6
+ uses_html_body{%%
7
+ <h1>Test page</h1>
8
+ <div class="xhr-target"></div>
9
+ <div class="unrelated xhr-response">Unrelated</div>
10
+ %}
11
+
12
+ uses_feature_package :xhr_test
13
+
14
+ stubs_http_request('/xhr', :body => '<p class="real xhr-response">Hello, world</p>', :headers => {'X-JavascriptFeatures-Init' => 'load'})
15
+
16
+ should 'complete the XHR request' do
17
+ assert_selector_count 1, '.real.xhr-response'
18
+ end
19
+
20
+ should 'initialise the feature required by the XHR content' do
21
+ assert_match(/touched-by-load/, execute_js('jQuery(".real.xhr-response").attr("class")'))
22
+ end
23
+
24
+ should 'limit the scope of the feature required by the XHR content to the XHR content itself' do
25
+ assert_no_match(/touched-by-load/, execute_js('jQuery(".unrelated.xhr-response").attr("class")'))
26
+ end
27
+
28
+ should 're-run global initialisation code when the XHR completes, limited to the scope of the XHR content' do
29
+ assert_selector_count 1, '.real.xhr-response .touched-by-global-init'
30
+ assert_selector_count 1, '.unrelated.xhr-response .touched-by-global-init'
31
+ end
32
+
33
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: javascript_features
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - George Brocklehurst
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-15 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: jsmin
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: harmony
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: shoulda
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: redgreen
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: rack-test
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: jslint_on_rails
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ version_requirements: *id006
105
+ - !ruby/object:Gem::Dependency
106
+ name: activesupport
107
+ prerelease: false
108
+ requirement: &id007 !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ type: :development
118
+ version_requirements: *id007
119
+ - !ruby/object:Gem::Dependency
120
+ name: json
121
+ prerelease: false
122
+ requirement: &id008 !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ hash: 3
128
+ segments:
129
+ - 0
130
+ version: "0"
131
+ type: :development
132
+ version_requirements: *id008
133
+ description:
134
+ email: george.brocklehurst@gmail.com
135
+ executables: []
136
+
137
+ extensions: []
138
+
139
+ extra_rdoc_files: []
140
+
141
+ files:
142
+ - test/compiler_test.rb
143
+ - test/fixtures/public/javascripts/alternative/alternative.js
144
+ - test/fixtures/public/javascripts/javascript_test/disabled_feature.js
145
+ - test/fixtures/public/javascripts/javascript_test/enabled_feature.js
146
+ - test/fixtures/public/javascripts/javascript_test/global_feature.js
147
+ - test/fixtures/public/javascripts/lib/jquery_plugin.js
148
+ - test/fixtures/public/javascripts/main/my_feature.js
149
+ - test/fixtures/public/javascripts/xhr_test/global_load.js
150
+ - test/fixtures/public/javascripts/xhr_test/load.js
151
+ - test/fixtures/public/javascripts/xhr_test/xhr.js
152
+ - test/helper_test.rb
153
+ - test/javascript_test.rb
154
+ - test/jslint_test.rb
155
+ - test/rack_test.rb
156
+ - test/test_case_test.rb
157
+ - test/test_helper.rb
158
+ - test/xhr_test.rb
159
+ - lib/javascript_features/compiler.rb
160
+ - lib/javascript_features/helper.rb
161
+ - lib/javascript_features/test_case/servlet.rb
162
+ - lib/javascript_features/test_case.rb
163
+ - lib/javascript_features.rb
164
+ - lib/rack/javascript_features.rb
165
+ - rails/init.rb
166
+ has_rdoc: true
167
+ homepage: http://georgebrock.com
168
+ licenses: []
169
+
170
+ post_install_message:
171
+ rdoc_options: []
172
+
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ none: false
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ hash: 3
181
+ segments:
182
+ - 0
183
+ version: "0"
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ hash: 3
190
+ segments:
191
+ - 0
192
+ version: "0"
193
+ requirements: []
194
+
195
+ rubyforge_project:
196
+ rubygems_version: 1.4.2
197
+ signing_key:
198
+ specification_version: 3
199
+ summary: Structured, unobtrusive JavaScript for Rails applications
200
+ test_files: []
201
+