qedproject 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/qedproject +49 -0
- data/lib/qedproject/helpers.rb +17 -0
- data/lib/qedproject/libraries/backbone.rb +9 -0
- data/lib/qedproject/libraries/base.rb +105 -0
- data/lib/qedproject/libraries/jquery.rb +9 -0
- data/lib/qedproject/libraries/jquerytmpl.rb +9 -0
- data/lib/qedproject/libraries/knockout.rb +9 -0
- data/lib/qedproject/libraries/skeleton.rb +21 -0
- data/lib/qedproject/project.rb +185 -0
- data/lib/qedproject/version.rb +3 -0
- data/lib/qedproject.rb +14 -0
- data/templates/Guardfile +29 -0
- data/templates/Rakefile +25 -0
- data/templates/assets.yml +10 -0
- data/templates/index.html +35 -0
- data/templates/sampleSpec.coffee +0 -0
- data/templates/sampleSpec.js +7 -0
- data/templates/suite.html +23 -0
- data/vendor/backbone/VERSION +1 -0
- data/vendor/backbone/backbone-min.js +33 -0
- data/vendor/backbone/json2.js +480 -0
- data/vendor/backbone/underscore-min.js +27 -0
- data/vendor/jasmine/lib/jasmine-1.0.2/jasmine-html.js +188 -0
- data/vendor/jasmine/lib/jasmine-1.0.2/jasmine.css +166 -0
- data/vendor/jasmine/lib/jasmine-1.0.2/jasmine.js +2421 -0
- data/vendor/jquery/VERSION +1 -0
- data/vendor/jquery/jquery-1.6.2.min.js +18 -0
- data/vendor/jquerytmpl/VERSION +1 -0
- data/vendor/jquerytmpl/jquery.tmpl.min.js +10 -0
- data/vendor/knockout/VERSION +1 -0
- data/vendor/knockout/knockout-1.2.1.js +76 -0
- data/vendor/skeleton/VERSION +1 -0
- data/vendor/skeleton/apple-touch-icon-114x114.png +0 -0
- data/vendor/skeleton/apple-touch-icon-72x72.png +0 -0
- data/vendor/skeleton/apple-touch-icon.png +0 -0
- data/vendor/skeleton/base.css +335 -0
- data/vendor/skeleton/favicon.ico +0 -0
- data/vendor/skeleton/layout.css +58 -0
- data/vendor/skeleton/skeleton.css +236 -0
- data/vendor/skeleton/tabs.js +42 -0
- data/vendor/skeleton/templates/index.html +94 -0
- metadata +219 -0
data/bin/qedproject
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'qedproject'
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
banner = "QEDProject #{QEDProject::VERSION} (C) 2011 Brian P. Hogan\n"
|
7
|
+
banner << "-" * banner.length
|
8
|
+
puts banner
|
9
|
+
|
10
|
+
options = {}
|
11
|
+
LIBRARIES = QEDProject::Libraries::Base.libs.keys
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: qedproject <projectname> [options]"
|
14
|
+
|
15
|
+
|
16
|
+
opts.on('-s', '--sass', "Use SASS") do
|
17
|
+
options[:sass] = true
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('-c', '--coffee', "Use Coffeescript") do
|
21
|
+
options[:coffeescript] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on('-a', '--assets', "Use Jammit to manage assets") do
|
25
|
+
options[:jammit] = true
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on('-t', '--testing', "Set up testing with Jasmine") do
|
29
|
+
options[:testing] = true
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-l", "--libs [LIBRARIES]", "comma-separated list of libraries to include.\nLibraries are: #{LIBRARIES.join(",")}") do |libs|
|
33
|
+
options[:libs] = libs.split(",").collect{ |f| f.to_sym }
|
34
|
+
end
|
35
|
+
end.parse!
|
36
|
+
options[:verbose] = true
|
37
|
+
project = ARGV[0]
|
38
|
+
|
39
|
+
if project.nil?
|
40
|
+
puts "Specify a project. Use qedproject -h for options."
|
41
|
+
else
|
42
|
+
begin
|
43
|
+
QEDProject::Project.create(project, options)
|
44
|
+
rescue QEDProject::BadLibraryError => e
|
45
|
+
puts e.message
|
46
|
+
puts "QEDProject supports #{LIBRARIES.join(",")}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module QEDProject
|
2
|
+
module Helpers
|
3
|
+
# Reads a template from the file system,
|
4
|
+
# evaluates it with ERB
|
5
|
+
# places it in the output folder specified.
|
6
|
+
# Takes the binding context as the last parameter
|
7
|
+
# so that ERb has access to instance variables, etc.
|
8
|
+
# This works similar to how Rails and Sinatra templates
|
9
|
+
# work.
|
10
|
+
def render_template_to_file(template, file, context)
|
11
|
+
t = File.read(File.join(self.template_root, template))
|
12
|
+
File.open(file, "w") do |f|
|
13
|
+
f << ERB.new(t, nil, "-").result(context)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module QEDProject
|
2
|
+
module Libraries
|
3
|
+
|
4
|
+
class Base
|
5
|
+
include QEDProject::Helpers
|
6
|
+
|
7
|
+
attr_accessor :template_root, :lib_root, :project
|
8
|
+
class << self
|
9
|
+
|
10
|
+
attr_accessor :libs
|
11
|
+
|
12
|
+
# Support for DSL, for setting the library name
|
13
|
+
# when creating the adapter.
|
14
|
+
# Adds the library and class to QEDProject::Libraries::Base.libs hash
|
15
|
+
# and also creates a getter method on the adapter instance
|
16
|
+
def library(name)
|
17
|
+
QEDProject::Libraries::Base.libs ||= {}
|
18
|
+
QEDProject::Libraries::Base.libs[name] = self
|
19
|
+
class_eval do
|
20
|
+
define_method :library do
|
21
|
+
name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_js_files(files)
|
27
|
+
# define class method
|
28
|
+
m = class << self; self; end
|
29
|
+
m.send :define_method, :js_files do
|
30
|
+
files
|
31
|
+
end
|
32
|
+
|
33
|
+
# define instance method
|
34
|
+
class_eval do
|
35
|
+
define_method :js_files do
|
36
|
+
files
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# convenience method for the DSL for setting CSS files
|
42
|
+
def set_css_files(files)
|
43
|
+
# define class method to get the data out
|
44
|
+
m = class << self; self; end
|
45
|
+
m.send :define_method, :css_files do
|
46
|
+
files
|
47
|
+
end
|
48
|
+
|
49
|
+
class_eval do
|
50
|
+
define_method :css_files do
|
51
|
+
files
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# convenience method for the DSL for setting image files.
|
58
|
+
def set_image_files(files)
|
59
|
+
|
60
|
+
m = class << self; self; end
|
61
|
+
m.send :define_method, :image_files do
|
62
|
+
files
|
63
|
+
end
|
64
|
+
|
65
|
+
class_eval do
|
66
|
+
define_method :image_files do
|
67
|
+
files
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize(project)
|
74
|
+
@project = project
|
75
|
+
@lib_root = File.join(@project.vendor_root, self.library.to_s)
|
76
|
+
@template_root = File.join(@lib_root, "templates")
|
77
|
+
end
|
78
|
+
|
79
|
+
def generate!
|
80
|
+
self.copy_js if self.respond_to?(:js_files) && self.js_files.any?
|
81
|
+
self.copy_css if self.respond_to?(:css_files) && self.css_files.any?
|
82
|
+
self.copy_images if self.respond_to?(:image_files) && self.image_files.any?
|
83
|
+
end
|
84
|
+
|
85
|
+
def copy_images
|
86
|
+
self.image_files.each do |lib|
|
87
|
+
::FileUtils.cp_r File.join(self.lib_root, lib), File.join(self.project.path, self.project.images_path), :verbose => self.project.verbose
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def copy_css
|
92
|
+
self.css_files.each do |lib|
|
93
|
+
::FileUtils.cp_r File.join(self.lib_root, lib), File.join(self.project.path, self.project.css_path), :verbose => self.project.verbose
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def copy_js
|
98
|
+
self.js_files.each do |lib|
|
99
|
+
::FileUtils.cp_r File.join(self.lib_root, lib), File.join(self.project.path, self.project.js_path), :verbose => self.project.verbose
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module QEDProject
|
2
|
+
module Libraries
|
3
|
+
class Skeleton < QEDProject::Libraries::Base
|
4
|
+
library :skeleton
|
5
|
+
set_js_files ["tabs.js"]
|
6
|
+
set_css_files ["base.css", "skeleton.css", "layout.css" ]
|
7
|
+
set_image_files [
|
8
|
+
"apple-touch-icon-114x114.png",
|
9
|
+
"apple-touch-icon-72x72.png",
|
10
|
+
"apple-touch-icon.png",
|
11
|
+
"favicon.ico"
|
12
|
+
]
|
13
|
+
|
14
|
+
def generate!
|
15
|
+
super
|
16
|
+
render_template_to_file "index.html", File.join(self.project.path, "public", "index.html"), binding
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
module QEDProject
|
4
|
+
|
5
|
+
class Project
|
6
|
+
|
7
|
+
include QEDProject::Helpers
|
8
|
+
|
9
|
+
attr_accessor :path, :libs, :coffeescript, :sass, :jammit,
|
10
|
+
:js_path, :css_path, :images_path, :verbose, :testing
|
11
|
+
# convenience method to create a new project.
|
12
|
+
# Simply call create with the project path and the options.
|
13
|
+
def self.create(project_path, options= {})
|
14
|
+
self.new(project_path, options).generate
|
15
|
+
end
|
16
|
+
|
17
|
+
def template_root
|
18
|
+
File.expand_path("../../../templates", __FILE__)
|
19
|
+
end
|
20
|
+
|
21
|
+
def vendor_root
|
22
|
+
File.expand_path("../../../vendor", __FILE__)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a new Project instance.
|
26
|
+
# Options:
|
27
|
+
# :libs : A list of js libraries to include, Can be :backbone, :jquery, :knockout
|
28
|
+
# :jammit: boolean, should Jammit be included?
|
29
|
+
# :coffeescript : Should CoffeeScript support be included?
|
30
|
+
# :sass Should sass support be included?
|
31
|
+
def initialize(project_path, options = {})
|
32
|
+
self.path = project_path
|
33
|
+
self.process_options(options)
|
34
|
+
self.set_paths
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Convenience method for showing all of the JavaScript files that
|
39
|
+
# the project should contain. Good for creating asset lists
|
40
|
+
# and loading files in rendered templates
|
41
|
+
def js_assets
|
42
|
+
libs.inject([]) do |original, lib|
|
43
|
+
if QEDProject::Libraries::Base.libs[lib].respond_to?(:js_files)
|
44
|
+
original += QEDProject::Libraries::Base.libs[lib].js_files
|
45
|
+
else
|
46
|
+
original
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Convenience method for showing all of the css files that
|
52
|
+
# the project should contain. Good for creating asset lists
|
53
|
+
# and loading files in rendered templates
|
54
|
+
def css_assets
|
55
|
+
libs.inject([]) do |original, lib|
|
56
|
+
if QEDProject::Libraries::Base.libs[lib].respond_to?(:css_files)
|
57
|
+
original += QEDProject::Libraries::Base.libs[lib].css_files
|
58
|
+
else
|
59
|
+
original
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Sets instance methods with values from the options hash.
|
65
|
+
def process_options(options)
|
66
|
+
self.libs = options[:libs] || []
|
67
|
+
|
68
|
+
libs.each do |lib|
|
69
|
+
raise QEDProject::BadLibraryError, "#{lib} is not a valid library" unless QEDProject::Libraries::Base.libs.include? lib
|
70
|
+
end
|
71
|
+
|
72
|
+
self.jammit = options[:jammit]
|
73
|
+
self.sass = options[:sass]
|
74
|
+
self.coffeescript = options[:coffeescript]
|
75
|
+
self.verbose = options[:verbose]
|
76
|
+
self.testing = options[:testing]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Set up the basic paths we'll use throughout
|
80
|
+
def set_paths
|
81
|
+
self.images_path = File.join("public", "images")
|
82
|
+
self.js_path = self.jammit ? "javascripts" : File.join("public", "javascripts")
|
83
|
+
self.css_path = self.jammit ? "stylesheets" : File.join("public", "stylesheets")
|
84
|
+
end
|
85
|
+
|
86
|
+
# We need a guardfile if the user is using jammit, sass, or coffeescript.
|
87
|
+
def needs_guardfile?
|
88
|
+
self.jammit || self.sass || self.coffeescript
|
89
|
+
end
|
90
|
+
|
91
|
+
# Only jammit needs a config folder for now.
|
92
|
+
def needs_config_folder?
|
93
|
+
self.jammit
|
94
|
+
end
|
95
|
+
|
96
|
+
# Start the project generation.
|
97
|
+
# Create the folder
|
98
|
+
# Get all of the libraries
|
99
|
+
# create an assets file if needed
|
100
|
+
# add the testing folder if needed
|
101
|
+
# create a guardfile if needed
|
102
|
+
def generate
|
103
|
+
self.create_project_skeleton
|
104
|
+
self.create_index
|
105
|
+
self.get_libraries if self.libs
|
106
|
+
self.create_asset_file if self.jammit
|
107
|
+
self.add_testing if self.testing
|
108
|
+
self.create_guardfile if self.needs_guardfile?
|
109
|
+
self.create_rakefile
|
110
|
+
end
|
111
|
+
|
112
|
+
# includes the Jasmine BDD framework for javascript testing
|
113
|
+
def add_testing
|
114
|
+
FileUtils.mkdir_p File.join(self.path, "spec"), :verbose => self.verbose
|
115
|
+
FileUtils.cp_r File.join(self.vendor_root, "jasmine", "lib"),
|
116
|
+
File.join(self.path, "spec", "lib"), :verbose => self.verbose
|
117
|
+
|
118
|
+
|
119
|
+
render_template_to_file "suite.html", File.join(self.path, "spec", "suite.html"), binding
|
120
|
+
if self.coffeescript
|
121
|
+
render_template_to_file "sampleSpec.coffee", File.join(self.path, "spec", "sampleSpec.coffee"), binding
|
122
|
+
else
|
123
|
+
render_template_to_file "sampleSpec.js", File.join(self.path, "spec", "sampleSpec.js"), binding
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
# Set up the main project skeleton
|
129
|
+
# project
|
130
|
+
# public/
|
131
|
+
# assets/ * only with assets
|
132
|
+
# images/
|
133
|
+
# javascripts/ * only without assets
|
134
|
+
# stylesheets/ * only without assets
|
135
|
+
# config/
|
136
|
+
# assets.yml * optional
|
137
|
+
# coffeescripts/ * optional
|
138
|
+
# sass/ * optional
|
139
|
+
# spec/ * optional
|
140
|
+
# Guardfile * optional
|
141
|
+
def create_project_skeleton
|
142
|
+
::FileUtils.mkdir_p( self.path, :verbose => self.verbose)
|
143
|
+
::FileUtils.mkdir_p( File.join(self.path, "public"), :verbose => self.verbose)
|
144
|
+
::FileUtils.mkdir_p( File.join(self.path, self.images_path), :verbose => self.verbose)
|
145
|
+
::FileUtils.mkdir_p( File.join(self.path, "tmp"), :verbose => self.verbose)
|
146
|
+
::FileUtils.mkdir_p( File.join(self.path, self.js_path), :verbose => self.verbose)
|
147
|
+
::FileUtils.mkdir_p( File.join(self.path, self.css_path), :verbose => self.verbose)
|
148
|
+
::FileUtils.mkdir_p( File.join(self.path, "config"), :verbose => self.verbose) if self.needs_config_folder?
|
149
|
+
::FileUtils.mkdir_p( File.join(self.path, "coffeescripts"), :verbose => self.verbose) if self.coffeescript
|
150
|
+
::FileUtils.mkdir_p( File.join(self.path, "sass"), :verbose => self.verbose) if self.sass
|
151
|
+
end
|
152
|
+
|
153
|
+
# Loop through the libraries the user added
|
154
|
+
# and run their generate methods
|
155
|
+
# which pulls in the additional optional files.
|
156
|
+
def get_libraries
|
157
|
+
libs.each do |lib|
|
158
|
+
library = QEDProject::Libraries::Base.libs[lib]
|
159
|
+
l = library.new(self)
|
160
|
+
l.generate!
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def create_asset_file
|
165
|
+
render_template_to_file("assets.yml", File.join(self.path, "config", "assets.yml"), binding)
|
166
|
+
puts "Created #{File.join(self.path, 'config', 'assets.yml')}" if self.verbose
|
167
|
+
end
|
168
|
+
|
169
|
+
def create_guardfile
|
170
|
+
render_template_to_file "Guardfile", File.join(self.path, "Guardfile"), binding
|
171
|
+
puts "Created #{ File.join(self.path, "Guardfile")}" if self.verbose
|
172
|
+
end
|
173
|
+
|
174
|
+
def create_index
|
175
|
+
@project = self
|
176
|
+
render_template_to_file "index.html", File.join(self.path, "public", "index.html"), binding
|
177
|
+
puts "Created #{ File.join(self.path, "public", "index.html")}" if self.verbose
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_rakefile
|
181
|
+
render_template_to_file "Rakefile", File.join(self.path, "Rakefile"), binding
|
182
|
+
puts "Created #{ File.join(self.path, "Rakefile")}" if self.verbose
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/qedproject.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "qedproject/version"
|
2
|
+
require "qedproject/helpers"
|
3
|
+
require "qedproject/libraries/base"
|
4
|
+
require "qedproject/libraries/jquery"
|
5
|
+
require "qedproject/libraries/backbone"
|
6
|
+
require "qedproject/libraries/knockout"
|
7
|
+
require "qedproject/libraries/jquerytmpl"
|
8
|
+
require "qedproject/libraries/skeleton"
|
9
|
+
require "qedproject/project"
|
10
|
+
|
11
|
+
module QEDProject
|
12
|
+
class BadLibraryError < RuntimeError
|
13
|
+
end
|
14
|
+
end
|
data/templates/Guardfile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
<% if self.sass -%>
|
2
|
+
<% if self.jammit -%>
|
3
|
+
guard "sass", :input => "sass", :output => "tmp"
|
4
|
+
<% else -%>
|
5
|
+
guard "sass", :input => "sass", :output => "public/stylesheets"
|
6
|
+
<% end -%>
|
7
|
+
<% end -%>
|
8
|
+
<% if self.coffeescript -%>
|
9
|
+
<% if self.jammit -%>
|
10
|
+
guard "coffeescript", :input => "coffeescripts", :output => "tmp"
|
11
|
+
<% else -%>
|
12
|
+
guard "coffeescript", :input => "coffeescripts", :output => "public/javascripts"
|
13
|
+
<% end -%>
|
14
|
+
<% if self.testing -%>
|
15
|
+
guard "coffeescript", :input => "spec", :output => "spec"
|
16
|
+
<% end -%>
|
17
|
+
<% end -%>
|
18
|
+
<% if self.jammit -%>
|
19
|
+
guard "jammit" do
|
20
|
+
watch(/^javascripts\\/(.*)\.js/)
|
21
|
+
watch(/^stylesheets\\/(.*)\.css/)
|
22
|
+
<% if self.coffeescript -%>
|
23
|
+
watch(/^tmp\\/(.*)\\.js/)
|
24
|
+
<% end -%>
|
25
|
+
<% if self.sass -%>
|
26
|
+
watch(/^tmp\\/(.*)\\.css/)
|
27
|
+
<% end -%>
|
28
|
+
end
|
29
|
+
<% end -%>
|
data/templates/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
SERVER = "yourhost.com"
|
2
|
+
USERNAME = "yourusername"
|
3
|
+
REMOTE_FOLDER = "/home/#{USERNAME}/yourhost.com"
|
4
|
+
|
5
|
+
require 'net/scp'
|
6
|
+
|
7
|
+
<% if self.needs_guardfile? -%>
|
8
|
+
desc "compile CSS, js files"
|
9
|
+
task :compile do
|
10
|
+
require 'guard'
|
11
|
+
Guard.setup
|
12
|
+
Guard::Dsl.evaluate_guardfile
|
13
|
+
Guard::guards.each{|guard| guard.run_all}
|
14
|
+
end
|
15
|
+
<% end -%>
|
16
|
+
desc "Deploy web site"
|
17
|
+
<% if self.needs_guardfile? -%>
|
18
|
+
task :deploy => :compile do
|
19
|
+
<% else -%>
|
20
|
+
task :deploy do
|
21
|
+
<% end -%>
|
22
|
+
Net::SCP.start(SERVER, USERNAME, {:port => PORT} ) do |scp|
|
23
|
+
scp.upload! "public", REMOTE_FOLDER, :recursive => true
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Project</title>
|
5
|
+
<% if @project.jammit %>
|
6
|
+
<link rel="stylesheet" href="assets/app.css">
|
7
|
+
<% else -%>
|
8
|
+
<link rel="stylesheet" href="stylesheets/style.css">
|
9
|
+
<% end -%>
|
10
|
+
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
|
14
|
+
<h1>My Project</h1>
|
15
|
+
|
16
|
+
<p>
|
17
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
|
18
|
+
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
|
19
|
+
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
20
|
+
aliquip ex ea commodo consequat. Duis aute irure dolor in
|
21
|
+
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
22
|
+
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
23
|
+
culpa qui officia deserunt mollit anim id est laborum.
|
24
|
+
</p>
|
25
|
+
|
26
|
+
|
27
|
+
<% if @project.jammit %>
|
28
|
+
<script src="assets/app.js"></script>
|
29
|
+
<% else -%>
|
30
|
+
<% @project.js_assets.each do |js| -%>
|
31
|
+
<script src="javascripts/<%=js %>"></script>
|
32
|
+
<% end -%>
|
33
|
+
<% end -%>
|
34
|
+
</body>
|
35
|
+
</html>
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Jasmine Test Runner</title>
|
5
|
+
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.0.2/jasmine.css">
|
6
|
+
<script type="text/javascript" src="lib/jasmine-1.0.2/jasmine.js"></script>
|
7
|
+
<script type="text/javascript" src="lib/jasmine-1.0.2/jasmine-html.js"></script>
|
8
|
+
|
9
|
+
<!-- include source files here... -->
|
10
|
+
|
11
|
+
<!-- include spec files here... -->
|
12
|
+
<script type="text/javascript" src="sampleSpec.js"></script>
|
13
|
+
|
14
|
+
</head>
|
15
|
+
<body>
|
16
|
+
|
17
|
+
<script type="text/javascript">
|
18
|
+
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
19
|
+
jasmine.getEnv().execute();
|
20
|
+
</script>
|
21
|
+
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
0.5.3
|
@@ -0,0 +1,33 @@
|
|
1
|
+
// Backbone.js 0.5.3
|
2
|
+
// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
|
3
|
+
// Backbone may be freely distributed under the MIT license.
|
4
|
+
// For all details and documentation:
|
5
|
+
// http://documentcloud.github.com/backbone
|
6
|
+
(function(){var h=this,p=h.Backbone,e;e=typeof exports!=="undefined"?exports:h.Backbone={};e.VERSION="0.5.3";var f=h._;if(!f&&typeof require!=="undefined")f=require("underscore")._;var g=h.jQuery||h.Zepto;e.noConflict=function(){h.Backbone=p;return this};e.emulateHTTP=!1;e.emulateJSON=!1;e.Events={bind:function(a,b,c){var d=this._callbacks||(this._callbacks={});(d[a]||(d[a]=[])).push([b,c]);return this},unbind:function(a,b){var c;if(a){if(c=this._callbacks)if(b){c=c[a];if(!c)return this;for(var d=
|
7
|
+
0,e=c.length;d<e;d++)if(c[d]&&b===c[d][0]){c[d]=null;break}}else c[a]=[]}else this._callbacks={};return this},trigger:function(a){var b,c,d,e,f=2;if(!(c=this._callbacks))return this;for(;f--;)if(b=f?a:"all",b=c[b])for(var g=0,h=b.length;g<h;g++)(d=b[g])?(e=f?Array.prototype.slice.call(arguments,1):arguments,d[0].apply(d[1]||this,e)):(b.splice(g,1),g--,h--);return this}};e.Model=function(a,b){var c;a||(a={});if(c=this.defaults)f.isFunction(c)&&(c=c.call(this)),a=f.extend({},c,a);this.attributes={};
|
8
|
+
this._escapedAttributes={};this.cid=f.uniqueId("c");this.set(a,{silent:!0});this._changed=!1;this._previousAttributes=f.clone(this.attributes);if(b&&b.collection)this.collection=b.collection;this.initialize(a,b)};f.extend(e.Model.prototype,e.Events,{_previousAttributes:null,_changed:!1,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.attributes[a];
|
9
|
+
return this._escapedAttributes[a]=(b==null?"":""+b).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")},has:function(a){return this.attributes[a]!=null},set:function(a,b){b||(b={});if(!a)return this;if(a.attributes)a=a.attributes;var c=this.attributes,d=this._escapedAttributes;if(!b.silent&&this.validate&&!this._performValidation(a,b))return!1;if(this.idAttribute in a)this.id=a[this.idAttribute];
|
10
|
+
var e=this._changing;this._changing=!0;for(var g in a){var h=a[g];if(!f.isEqual(c[g],h))c[g]=h,delete d[g],this._changed=!0,b.silent||this.trigger("change:"+g,this,h,b)}!e&&!b.silent&&this._changed&&this.change(b);this._changing=!1;return this},unset:function(a,b){if(!(a in this.attributes))return this;b||(b={});var c={};c[a]=void 0;if(!b.silent&&this.validate&&!this._performValidation(c,b))return!1;delete this.attributes[a];delete this._escapedAttributes[a];a==this.idAttribute&&delete this.id;this._changed=
|
11
|
+
!0;b.silent||(this.trigger("change:"+a,this,void 0,b),this.change(b));return this},clear:function(a){a||(a={});var b,c=this.attributes,d={};for(b in c)d[b]=void 0;if(!a.silent&&this.validate&&!this._performValidation(d,a))return!1;this.attributes={};this._escapedAttributes={};this._changed=!0;if(!a.silent){for(b in c)this.trigger("change:"+b,this,void 0,a);this.change(a)}return this},fetch:function(a){a||(a={});var b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&
|
12
|
+
c(b,d)};a.error=i(a.error,b,a);return(this.sync||e.sync).call(this,"read",this,a)},save:function(a,b){b||(b={});if(a&&!this.set(a,b))return!1;var c=this,d=b.success;b.success=function(a,e,f){if(!c.set(c.parse(a,f),b))return!1;d&&d(c,a,f)};b.error=i(b.error,c,b);var f=this.isNew()?"create":"update";return(this.sync||e.sync).call(this,f,this,b)},destroy:function(a){a||(a={});if(this.isNew())return this.trigger("destroy",this,this.collection,a);var b=this,c=a.success;a.success=function(d){b.trigger("destroy",
|
13
|
+
b,b.collection,a);c&&c(b,d)};a.error=i(a.error,b,a);return(this.sync||e.sync).call(this,"delete",this,a)},url:function(){var a=k(this.collection)||this.urlRoot||l();if(this.isNew())return a;return a+(a.charAt(a.length-1)=="/"?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this)},isNew:function(){return this.id==null},change:function(a){this.trigger("change",this,a);this._previousAttributes=f.clone(this.attributes);this._changed=!1},hasChanged:function(a){if(a)return this._previousAttributes[a]!=
|
14
|
+
this.attributes[a];return this._changed},changedAttributes:function(a){a||(a=this.attributes);var b=this._previousAttributes,c=!1,d;for(d in a)f.isEqual(b[d],a[d])||(c=c||{},c[d]=a[d]);return c},previous:function(a){if(!a||!this._previousAttributes)return null;return this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},_performValidation:function(a,b){var c=this.validate(a);if(c)return b.error?b.error(this,c,b):this.trigger("error",this,c,b),!1;return!0}});
|
15
|
+
e.Collection=function(a,b){b||(b={});if(b.comparator)this.comparator=b.comparator;f.bindAll(this,"_onModelEvent","_removeReference");this._reset();a&&this.reset(a,{silent:!0});this.initialize.apply(this,arguments)};f.extend(e.Collection.prototype,e.Events,{model:e.Model,initialize:function(){},toJSON:function(){return this.map(function(a){return a.toJSON()})},add:function(a,b){if(f.isArray(a))for(var c=0,d=a.length;c<d;c++)this._add(a[c],b);else this._add(a,b);return this},remove:function(a,b){if(f.isArray(a))for(var c=
|
16
|
+
0,d=a.length;c<d;c++)this._remove(a[c],b);else this._remove(a,b);return this},get:function(a){if(a==null)return null;return this._byId[a.id!=null?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");this.models=this.sortBy(this.comparator);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},
|
17
|
+
reset:function(a,b){a||(a=[]);b||(b={});this.each(this._removeReference);this._reset();this.add(a,{silent:!0});b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a||(a={});var b=this,c=a.success;a.success=function(d,f,e){b[a.add?"add":"reset"](b.parse(d,e),a);c&&c(b,d)};a.error=i(a.error,b,a);return(this.sync||e.sync).call(this,"read",this,a)},create:function(a,b){var c=this;b||(b={});a=this._prepareModel(a,b);if(!a)return!1;var d=b.success;b.success=function(a,e,f){c.add(a,b);
|
18
|
+
d&&d(a,e,f)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId={};this._byCid={}},_prepareModel:function(a,b){if(a instanceof e.Model){if(!a.collection)a.collection=this}else{var c=a;a=new this.model(c,{collection:this});a.validate&&!a._performValidation(c,b)&&(a=!1)}return a},_add:function(a,b){b||(b={});a=this._prepareModel(a,b);if(!a)return!1;var c=this.getByCid(a);if(c)throw Error(["Can't add the same model to a set twice",
|
19
|
+
c.id]);this._byId[a.id]=a;this._byCid[a.cid]=a;this.models.splice(b.at!=null?b.at:this.comparator?this.sortedIndex(a,this.comparator):this.length,0,a);a.bind("all",this._onModelEvent);this.length++;b.silent||a.trigger("add",a,this,b);return a},_remove:function(a,b){b||(b={});a=this.getByCid(a)||this.get(a);if(!a)return null;delete this._byId[a.id];delete this._byCid[a.cid];this.models.splice(this.indexOf(a),1);this.length--;b.silent||a.trigger("remove",a,this,b);this._removeReference(a);return a},
|
20
|
+
_removeReference:function(a){this==a.collection&&delete a.collection;a.unbind("all",this._onModelEvent)},_onModelEvent:function(a,b,c,d){(a=="add"||a=="remove")&&c!=this||(a=="destroy"&&this._remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,arguments))}});f.each(["forEach","each","map","reduce","reduceRight","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","max",
|
21
|
+
"min","sortBy","sortedIndex","toArray","size","first","rest","last","without","indexOf","lastIndexOf","isEmpty","groupBy"],function(a){e.Collection.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});e.Router=function(a){a||(a={});if(a.routes)this.routes=a.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var q=/:([\w\d]+)/g,r=/\*([\w\d]+)/g,s=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(e.Router.prototype,e.Events,{initialize:function(){},route:function(a,
|
22
|
+
b,c){e.history||(e.history=new e.History);f.isRegExp(a)||(a=this._routeToRegExp(a));e.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d))},this))},navigate:function(a,b){e.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(s,"\\$&").replace(q,
|
23
|
+
"([^/]*)").replace(r,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});e.History=function(){this.handlers=[];f.bindAll(this,"checkUrl")};var j=/^#*/,t=/msie [\w.]+/,m=!1;f.extend(e.History.prototype,{interval:50,getFragment:function(a,b){if(a==null)if(this._hasPushState||b){a=window.location.pathname;var c=window.location.search;c&&(a+=c);a.indexOf(this.options.root)==0&&(a=a.substr(this.options.root.length))}else a=window.location.hash;return decodeURIComponent(a.replace(j,
|
24
|
+
""))},start:function(a){if(m)throw Error("Backbone.history has already been started");this.options=f.extend({},{root:"/"},this.options,a);this._wantsPushState=!!this.options.pushState;this._hasPushState=!(!this.options.pushState||!window.history||!window.history.pushState);a=this.getFragment();var b=document.documentMode;if(b=t.exec(navigator.userAgent.toLowerCase())&&(!b||b<=7))this.iframe=g('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);
|
25
|
+
this._hasPushState?g(window).bind("popstate",this.checkUrl):"onhashchange"in window&&!b?g(window).bind("hashchange",this.checkUrl):setInterval(this.checkUrl,this.interval);this.fragment=a;m=!0;a=window.location;b=a.pathname==this.options.root;if(this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+"#"+this.fragment),!0;else if(this._wantsPushState&&this._hasPushState&&b&&a.hash)this.fragment=a.hash.replace(j,""),window.history.replaceState({},
|
26
|
+
document.title,a.protocol+"//"+a.host+this.options.root+this.fragment);if(!this.options.silent)return this.loadUrl()},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.iframe.location.hash));if(a==this.fragment||a==decodeURIComponent(this.fragment))return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(window.location.hash)},loadUrl:function(a){var b=this.fragment=this.getFragment(a);
|
27
|
+
return f.any(this.handlers,function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){var c=(a||"").replace(j,"");if(!(this.fragment==c||this.fragment==decodeURIComponent(c))){if(this._hasPushState){var d=window.location;c.indexOf(this.options.root)!=0&&(c=this.options.root+c);this.fragment=c;window.history.pushState({},document.title,d.protocol+"//"+d.host+c)}else if(window.location.hash=this.fragment=c,this.iframe&&c!=this.getFragment(this.iframe.location.hash))this.iframe.document.open().close(),
|
28
|
+
this.iframe.location.hash=c;b&&this.loadUrl(a)}}});e.View=function(a){this.cid=f.uniqueId("view");this._configure(a||{});this._ensureElement();this.delegateEvents();this.initialize.apply(this,arguments)};var u=/^(\S+)\s*(.*)$/,n=["model","collection","el","id","attributes","className","tagName"];f.extend(e.View.prototype,e.Events,{tagName:"div",$:function(a){return g(a,this.el)},initialize:function(){},render:function(){return this},remove:function(){g(this.el).remove();return this},make:function(a,
|
29
|
+
b,c){a=document.createElement(a);b&&g(a).attr(b);c&&g(a).html(c);return a},delegateEvents:function(a){if(a||(a=this.events))for(var b in f.isFunction(a)&&(a=a.call(this)),g(this.el).unbind(".delegateEvents"+this.cid),a){var c=this[a[b]];if(!c)throw Error('Event "'+a[b]+'" does not exist');var d=b.match(u),e=d[1];d=d[2];c=f.bind(c,this);e+=".delegateEvents"+this.cid;d===""?g(this.el).bind(e,c):g(this.el).delegate(d,e,c)}},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=
|
30
|
+
0,c=n.length;b<c;b++){var d=n[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el){if(f.isString(this.el))this.el=g(this.el).get(0)}else{var a=this.attributes||{};if(this.id)a.id=this.id;if(this.className)a["class"]=this.className;this.el=this.make(this.tagName,a)}}});e.Model.extend=e.Collection.extend=e.Router.extend=e.View.extend=function(a,b){var c=v(this,a,b);c.extend=this.extend;return c};var w={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};e.sync=function(a,
|
31
|
+
b,c){var d=w[a];c=f.extend({type:d,dataType:"json"},c);if(!c.url)c.url=k(b)||l();if(!c.data&&b&&(a=="create"||a=="update"))c.contentType="application/json",c.data=JSON.stringify(b.toJSON());if(e.emulateJSON)c.contentType="application/x-www-form-urlencoded",c.data=c.data?{model:c.data}:{};if(e.emulateHTTP&&(d==="PUT"||d==="DELETE")){if(e.emulateJSON)c.data._method=d;c.type="POST";c.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d)}}if(c.type!=="GET"&&!e.emulateJSON)c.processData=
|
32
|
+
!1;return g.ajax(c)};var o=function(){},v=function(a,b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){return a.apply(this,arguments)};f.extend(d,a);o.prototype=a.prototype;d.prototype=new o;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},k=function(a){if(!a||!a.url)return null;return f.isFunction(a.url)?a.url():a.url},l=function(){throw Error('A "url" property or function must be specified');},i=function(a,b,c){return function(d){a?
|
33
|
+
a(b,d,c):b.trigger("error",b,d,c)}}}).call(this);
|