sinatra-backbone-2 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b298438993e405f71dbfc8505c9a13ad08c2d602
4
+ data.tar.gz: bf4f06c3d7025a750daf0ed27b12b9bb225103c4
5
+ SHA512:
6
+ metadata.gz: 5436faf91a0139869f3d43e1c7cd0e8786529c24a61253e8314766bbc13ec7739da3d289d06d97f56e0092ce012dd1acf589608323b274cf2e2ad9f7ae0a461f
7
+ data.tar.gz: 2de609aa39dd72b0771f388942f35c5460ff0fb67f29e8a566d7b29cec84da81db1c8a0176739be276d58be991b5a2e4c3c7d5e2c710f3d0e843a6349a8a5289
@@ -0,0 +1,2 @@
1
+ /doc
2
+ /Gemfile.lock
@@ -0,0 +1,10 @@
1
+ ---
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 2.0.0
6
+ matrix:
7
+ include:
8
+ - { rvm: 2.0.0, env: sinatra=1.3 }
9
+ - { rvm: 2.0.0, env: sinatra=1.4 }
10
+ - { rvm: 2.0.0, env: sinatra=master }
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ case ENV['sinatra']
5
+ when '1.3' then gem 'sinatra', '~> 1.3.0'
6
+ when '1.4' then gem 'sinatra', '~> 1.4.0'
7
+ when 'master' then gem 'sinatra', :github => 'sinatra/sinatra', :branch => 'master'
8
+ end
@@ -0,0 +1,23 @@
1
+ v0.1.1 - Apr 17, 2013
2
+ ---------------------
3
+
4
+ * Allow `.jst` file extensions. (in addition to `.jst.eco` and similar)
5
+ * Check for validity of models on the server.
6
+ * Documentation updates.
7
+ * Make the error message helpful if you forget #to_hash.
8
+ * Refactor rest_resource to split up into rest_edit, rest_delete and rest_get.
9
+ * Support multiple args in routes.
10
+
11
+ v0.1.0.rc2 - Sep 12, 2011
12
+ -------------------------
13
+
14
+ ### Changed:
15
+ * Check for validity of models on the server, and add an example.
16
+ * Added examples in the documentation.
17
+ * Support multiple args in routes.
18
+ * Added more tests.
19
+
20
+ v0.1.0.rc1 - Sept 12, 2011
21
+ --------------------------
22
+
23
+ Initial version.
@@ -0,0 +1,18 @@
1
+ Development notes
2
+ =================
3
+
4
+ ### Multiple Sinatra version testing
5
+
6
+ $ rake test!
7
+
8
+ Or a certain version:
9
+
10
+ $ sinatra=1.3 bundle exec rake test
11
+
12
+ ### Documentation
13
+
14
+ Install [reacco], then:
15
+
16
+ $ rake doc:build
17
+
18
+ [reacco]: https://github.com/rstacruz/reacco
@@ -0,0 +1,51 @@
1
+ # Sinatra-backbone
2
+ #### Neat integration of Backbone.js with Sinatra
3
+
4
+ Do you like [Backbone.js][bb]? Do you like [Sinatra][sn]? Did you ever wish you
5
+ can use them together? Well now you can, with the new Sinatra Backbone!
6
+
7
+ [bb]: http://documentcloud.github.com/backbone/
8
+ [sn]: http://sinatrarb.com
9
+
10
+ #### Usage
11
+
12
+ This is a Ruby gem.
13
+ `$ gem install sinatra-backbone --pre`
14
+
15
+ Or do you use Bundler?
16
+ `gem 'sinatra-backbone', :require => 'sinatra/backbone'`
17
+
18
+ Contents
19
+ --------
20
+
21
+ __Sinatra-backbone__ is comprised of two Sinatra plugins:
22
+
23
+ * `Sinatra::JstPages` – Provides support for JavaScript server templates (JST)
24
+ for use in Backbone views. See [JstPages example][jstx] for a full example
25
+ application.
26
+
27
+ * `Sinatra::RestAPI` – Provides restful API for your models for use in Backbone
28
+ models. See [RestAPI example][restx] for a full example application.
29
+
30
+ [jstx]: https://github.com/rstacruz/sinatra-backbone/tree/master/examples/jstpages
31
+ [restx]: https://github.com/rstacruz/sinatra-backbone/tree/master/examples/restapi
32
+
33
+ For usage and API reference, please see http://ricostacruz.com/sinatra-backbone. [](#api_reference)
34
+
35
+ Acknowledgements
36
+ ----------------
37
+
38
+ © 2011, Rico Sta. Cruz. Released under the [MIT
39
+ License](http://www.opensource.org/licenses/mit-license.php).
40
+
41
+ Sinatra-Backbone is authored and maintained by [Rico Sta. Cruz][rsc] with help
42
+ from its [contributors][c]. It is sponsored by my startup, [Sinefunc, Inc][sf].
43
+
44
+ * [My website](http://ricostacruz.com) (ricostacruz.com)
45
+ * [Sinefunc, Inc.](http://sinefunc.com) (sinefunc.com)
46
+ * [Github](http://github.com/rstacruz) (@rstacruz)
47
+ * [Twitter](http://twitter.com/rstacruz) (@rstacruz)
48
+
49
+ [rsc]: http://ricostacruz.com
50
+ [c]: http://github.com/rstacruz/xxxxx
51
+ [sf]: http://sinefunc.com
@@ -0,0 +1,34 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ desc "Invokes the test suite in multiple RVM environments"
4
+ task :'test!' do
5
+ %w[1.3 1.4 master].each do |version|
6
+ env = "env sinatra=#{version}"
7
+ system("rm -f Gemfile.lock; #{env} bundle && #{env} bundle exec rake test") or abort
8
+ end
9
+ end
10
+
11
+ desc "Runs tests"
12
+ task :test do
13
+ Dir['test/*_test.rb'].each { |f| load f }
14
+ end
15
+
16
+ task :default => :test
17
+
18
+ repo = ENV['GITHUB_REPO'] || 'rstacruz/sinatra-backbone'
19
+ namespace :doc do
20
+ desc "Builds documentation"
21
+ task :build do
22
+ # github.com/rstacruz/reacco
23
+ analytics = "--analytics #{ENV['ANALYTICS_ID']}" if ENV['ANALYTICS_ID']
24
+ system "reacco --literate --toc --api lib --github #{repo} #{analytics}"
25
+ end
26
+
27
+ desc "Uploads documentation"
28
+ task :deploy => :build do
29
+ # github.com/rstacruz/git-update-ghpages
30
+ system "git update-ghpages -i doc #{repo}"
31
+ end
32
+ end
33
+
34
+ task :doc => :'doc:build'
@@ -0,0 +1,21 @@
1
+ $:.unshift File.expand_path('../../../lib', __FILE__)
2
+
3
+ require 'sinatra/base'
4
+ require 'sequel'
5
+ require 'sinatra/backbone'
6
+
7
+ class App < Sinatra::Base
8
+ enable :raise_errors, :logging
9
+ enable :show_exceptions if development?
10
+
11
+ register Sinatra::JstPages
12
+ serve_jst '/jst.js'
13
+
14
+ set :root, File.expand_path('../', __FILE__)
15
+ set :views, File.expand_path('../views', __FILE__)
16
+ set :public, File.expand_path('../public', __FILE__)
17
+
18
+ get '/' do
19
+ erb :home
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ require './app'
2
+ App.set :run, false
3
+ run App
@@ -0,0 +1,20 @@
1
+ // Here is our Backbone model!
2
+ $(function() {
3
+ do_test();
4
+ });
5
+
6
+ function do_test() {
7
+ echo("<h3>Rendering from template:</h3>");
8
+ echo(JST['hello']({name: "Julie Kitzinger", age: "33"}));
9
+ echo("<h3>Success!</h3>");
10
+ }
11
+
12
+ // Helper functions
13
+ function echo(html) {
14
+ $("#messages").append(html);
15
+ };
16
+
17
+ function onerror() {
18
+ echo("<p class='error'>Oops... an error occured.</p>");
19
+ };
20
+
@@ -0,0 +1,6 @@
1
+ <p>Hello, this is me:</p>
2
+
3
+ <dl>
4
+ <dt>Name:</dt><dd><%= name %></dd>
5
+ <dt>Age:</dt><dd><%= age %></dd>
6
+ </dl>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title></title>
6
+ <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.2/jquery.min.js'></script>
7
+ <script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.1.7/underscore-min.js'></script>
8
+ <script src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js'></script>
9
+ <style>
10
+ body { font-family: sans-serif; font-size: 13px; line-height: 1.5; background: #d0d0da; }
11
+ #messages { width: 400px; margin: 20px auto; background: white; padding: 20px; border: solid 10px #c0c0ca; }
12
+ h3 { border-top: dotted 1px #ccc; padding: 20px 20px 0 20px; margin: 20px -20px 0 -20px; color: #46a; }
13
+ h3:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
14
+ dl { overflow: hidden; }
15
+ dt { float: left; width: 120px; margin-right: 10px; text-align: right; color: #aaa; }
16
+ h3 { font-family: palatino; font-size: 1.3em; }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <div id="messages">
21
+ </div>
22
+ <script src='jst.js'></script>
23
+ <script src='app.js'></script>
24
+ </body>
25
+ </html>
@@ -0,0 +1,40 @@
1
+ $:.unshift File.expand_path('../../../lib', __FILE__)
2
+
3
+ require 'sinatra/base'
4
+ require 'sequel'
5
+ require 'sinatra/backbone'
6
+
7
+ DB = Sequel.connect("sqlite::memory:")
8
+ DB.create_table :books do
9
+ primary_key :id
10
+ String :title
11
+ String :author
12
+ end
13
+
14
+ class Book < Sequel::Model
15
+ def to_hash
16
+ { :id => id, :title => title, :author => author }
17
+ end
18
+
19
+ def validate
20
+ errors.add :author, "can't be empty" if author.to_s.size == 0
21
+ end
22
+ end
23
+
24
+ class App < Sinatra::Base
25
+ enable :raise_errors, :logging
26
+ enable :show_exceptions if development?
27
+
28
+ register Sinatra::RestAPI
29
+
30
+ rest_create("/book") { Book.new }
31
+ rest_resource("/book/:id") { |id| Book[id] }
32
+
33
+ set :root, File.expand_path('../', __FILE__)
34
+ set :views, File.expand_path('../', __FILE__)
35
+ set :public, File.expand_path('../public', __FILE__)
36
+
37
+ get '/' do
38
+ erb :home
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ require './app'
2
+ App.set :run, false
3
+ run App
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title></title>
6
+ <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.2/jquery.min.js'></script>
7
+ <script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.1.7/underscore-min.js'></script>
8
+ <script src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js'></script>
9
+ <style>
10
+ body { font-family: sans-serif; font-size: 13px; line-height: 1.5; background: #d0d0da; }
11
+ #messages { width: 400px; margin: 20px auto; background: white; padding: 20px; border: solid 10px #c0c0ca; }
12
+ h3 { border-top: dotted 1px #ccc; padding: 20px 20px 0 20px; margin: 20px -20px 0 -20px; color: #46a; }
13
+ h3:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
14
+ dl { overflow: hidden; }
15
+ dt { float: left; width: 120px; margin-right: 10px; text-align: right; color: #aaa; }
16
+ h3 { font-family: palatino; font-size: 1.3em; }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <div id="messages">
21
+ </div>
22
+ <script src='app.js'></script>
23
+ </body>
24
+ </html>
@@ -0,0 +1,105 @@
1
+ // Here is our Backbone model!
2
+ Book = Backbone.Model.extend({
3
+ urlRoot: '/book'
4
+ });
5
+
6
+ $(function() {
7
+ do_create();
8
+ });
9
+
10
+ function do_create() {
11
+ echo("<h3>Creating a book:</h3>");
12
+
13
+ var book = new Book;
14
+ book.set({ title: "Darkly Dreaming Dexter", author: "Jeff Lindsay" });
15
+ book.save({}, {
16
+ error: onerror,
17
+ success: function() {
18
+ print_book(book);
19
+ echo("<h3>Retrieving the same book:</h3>");
20
+ do_retrieve(book);
21
+ }
22
+ });
23
+ }
24
+
25
+ function do_retrieve(_book) {
26
+ var book = new Book({ id: _book.id });
27
+ book.fetch({
28
+ error: onerror,
29
+ success: function() {
30
+ print_book(book);
31
+ do_edit_error(book);
32
+ }
33
+ });
34
+ }
35
+
36
+ function do_edit_error(book) {
37
+ echo("<h3>Editing book with an error:</h3>");
38
+ console.log("(You should see an HTTP error right about here:)");
39
+ book.set({ author: '' });
40
+ book.save({}, {
41
+ success: onerror,
42
+ error: function() {
43
+ console.log("(...yep.)");
44
+ echo("...yes, it occured.");
45
+ do_edit(book);
46
+ }
47
+ });
48
+ }
49
+
50
+ function do_edit(book) {
51
+ echo("<h3>Editing book:</h3>");
52
+ book.set({ author: 'Anne Rice', title: 'The Claiming of Sleeping Beauty' });
53
+ book.save({}, {
54
+ error: onerror,
55
+ success: function() {
56
+ print_book(book);
57
+ do_delete(book);
58
+ }
59
+ });
60
+ }
61
+
62
+ function do_delete(book) {
63
+ echo("<h3>Deleting book:</h3>");
64
+ book.destroy({
65
+ error: onerror,
66
+ success: function() {
67
+ echo("Success.");
68
+ do_verify_delete(book.id);
69
+ }
70
+ });
71
+ }
72
+
73
+ function do_verify_delete(id) {
74
+ echo("<h3>Checking if book "+id+" still exists:</h3>");
75
+ console.log("(You should see an HTTP error right about here:)");
76
+ var book = new Book({ id: id });
77
+ book.fetch({
78
+ success: onerror,
79
+ error: function() {
80
+ console.log("(...yep.)");
81
+ echo("No, it doesn't.");
82
+ do_success();
83
+ }
84
+ });
85
+ }
86
+
87
+ function do_success() {
88
+ echo("<h3>Success!</h3>");
89
+ }
90
+
91
+ function print_book(book) {
92
+ echo("<dl><dt>Title:</dt><dd>"+book.get('title')+"</dd></dl>");
93
+ echo("<dl><dt>Author:</dt><dd>"+book.get('author')+"</dd></dl>");
94
+ echo("<dl><dt>ID:</dt><dd>"+book.get('id')+"</dd></dl>");
95
+ }
96
+
97
+ // Helper functions
98
+ function echo(html) {
99
+ $("#messages").append(html);
100
+ };
101
+
102
+ function onerror() {
103
+ echo("<p class='error'>Oops... an error occured.</p>");
104
+ };
105
+
@@ -0,0 +1,10 @@
1
+ module Sinatra
2
+ module Backbone
3
+ def self.version
4
+ "0.1.1"
5
+ end
6
+ end
7
+
8
+ autoload :RestAPI, "sinatra/restapi"
9
+ autoload :JstPages, "sinatra/jstpages"
10
+ end
@@ -0,0 +1,261 @@
1
+ # ## JstPages [module]
2
+ # A Sinatra plugin that adds support for JST (JavaScript Server Templates).
3
+ # See [JstPages example][jstx] for a full example application.
4
+ #
5
+ # ### Basic usage
6
+ # Register the `Sinatra::JstPages` plugin in your application, and use
7
+ # `serve_jst`. This example serves all JST files found in `/views/**/*.jst.*`
8
+ # (where `/views` is your views directory as defined in Sinatra's
9
+ # `settings.views`) as `http://localhost:4567/jst.js`.
10
+ #
11
+ # require 'sinatra/jstpages'
12
+ #
13
+ # class App < Sinatra::Base
14
+ # register Sinatra::JstPages
15
+ # serve_jst '/jst.js'
16
+ # end
17
+ #
18
+ # You will need to link to the JST route in your layout. Make a `<script>` tag
19
+ # where the `src='...'` attribute is the same path you provide to `serve_jst`.
20
+ #
21
+ # <script type='text/javascript' src='/jst.js'></script>
22
+ #
23
+ # So, if you have a JST view placed in `views/editor/edit.jst.tpl`:
24
+ #
25
+ # # views/editor/edit.jst.tpl
26
+ # <h1>Edit <%= name %></h1>
27
+ # <form>
28
+ # <button>Save</button>
29
+ # </form>
30
+ #
31
+ # Now in your browser you may invoke `JST['templatename']`:
32
+ #
33
+ # // Renders the editor/edit template
34
+ # JST['editor/edit']();
35
+ #
36
+ # // Renders the editor/edit template with template parameters
37
+ # JST['editor/edit']({name: 'Item Name'});
38
+ #
39
+ # #### Using Sinatra-AssetPack?
40
+ #
41
+ # __TIP:__ If you're using the [sinatra-assetpack][sap] gem, just add `/jst.js`
42
+ # to a package. (If you're not using Sinatra AssetPack yet, you probably
43
+ # should.)
44
+ #
45
+ # [sap]: http://ricostacruz.com/sinatra-assetpack
46
+ #
47
+ # ### Supported templates
48
+ #
49
+ # __[Jade][jade]__ (`.jst.jade`) -- Jade templates. This requires
50
+ # [jade.js][jade]. For older browsers, you will also need [json2.js][json2],
51
+ # and an implementation of [String.prototype.trim][trim].
52
+ #
53
+ # # views/editor/edit.jst.jade
54
+ # h1= "Edit "+name
55
+ # form
56
+ # button Save
57
+ #
58
+ # __[Underscore templates][under_tpl]__ (`.jst.tpl`) -- Simple templates by
59
+ # underscore. This requires [underscore.js][under], which Backbone also
60
+ # requires.
61
+ #
62
+ # # views/editor/edit.jst.tpl
63
+ # <h1>Edit <%= name %></h1>
64
+ # <form>
65
+ # <button>Save</button>
66
+ # </form>
67
+ #
68
+ # __[Haml.js][haml]__ (`.jst.haml`) -- A JavaScript implementation of Haml.
69
+ # Requires [haml.js][haml].
70
+ #
71
+ # # views/editor/edit.jst.haml
72
+ # %h1= "Edit "+name
73
+ # %form
74
+ # %button Save
75
+ #
76
+ # __[Eco][eco]__ (`.jst.eco`) -- Embedded CoffeeScript templates. Requires
77
+ # [eco.js][eco] and [coffee-script.js][cs].
78
+ #
79
+ # # views/editor/edit.jst.eco
80
+ # <h1>Edit <%= name %></h1>
81
+ # <form>
82
+ # <button>Save</button>
83
+ # </form>
84
+ #
85
+ # You can add support for more templates by subclassing the `Engine` class.
86
+ #
87
+ # [jade]: http://github.com/visionmedia/jade
88
+ # [json2]: https://github.com/douglascrockford/JSON-js
89
+ # [trim]: http://snippets.dzone.com/posts/show/701
90
+ # [under_tpl]: http://documentcloud.github.com/underscore/#template
91
+ # [under]: http://documentcloud.github.com/underscore
92
+ # [haml]: https://github.com/creationix/haml-js
93
+ # [eco]: https://github.com/sstephenson/eco
94
+ # [cs]: http://coffeescript.org
95
+ # [jstx]: https://github.com/rstacruz/sinatra-backbone/tree/master/examples/jstpages
96
+ #
97
+ module Sinatra
98
+ module JstPages
99
+ def self.registered(app)
100
+ app.extend ClassMethods
101
+ app.helpers Helpers
102
+ end
103
+
104
+ # Returns a hash to determine which engine is mapped onto a given extension.
105
+ def self.mappings
106
+ @mappings ||= Hash.new
107
+ end
108
+
109
+ def self.register(ext, engine)
110
+ mappings[ext] = engine
111
+ end
112
+
113
+ module Helpers
114
+ # Returns a list of JST files.
115
+ def jst_files(options = {})
116
+ # Tuples of [ name, Engine instance ]
117
+ root = options[:root] || settings.views
118
+ tuples = Dir.chdir(root) {
119
+ Dir["**/*.jst*"].map { |fn|
120
+ name = fn.match(%r{^(.*)\.jst})[1]
121
+ ext = fn.match(%r{\.([^\.]*)$})[1]
122
+ engine = JstPages.mappings[ext]
123
+
124
+ [ name, engine.new(name, File.join(root, fn)) ] if engine
125
+ }.compact
126
+ }
127
+
128
+ Hash[*tuples.flatten]
129
+ end
130
+ end
131
+
132
+ module ClassMethods
133
+ # ### serve_jst(path, [options]) [class method]
134
+ # Serves JST files in given `path`.
135
+ #
136
+ def serve_jst(path, options={})
137
+ get path do
138
+ content_type :js
139
+ jsts = jst_files(options).map do |(name, engine)|
140
+ engine.compile!
141
+ end
142
+
143
+ %{
144
+ (function(){
145
+ var c = {};
146
+ if (!window.JST) window.JST = {};
147
+ #{jsts.join("\n ")}
148
+ })();
149
+ }.strip.gsub(/^ {12}/, '')
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+
157
+ # ## JstPages::Engine [class]
158
+ # A template engine.
159
+ #
160
+ # #### Adding support for new template engines
161
+ # You will need to subclass `Engine`, override at least the `function` method,
162
+ # then use `JstPages.register`.
163
+ #
164
+ # This example will register `.jst.my` files to a new engine that uses
165
+ # `My.compile`.
166
+ #
167
+ # module Sinatra::JstPages
168
+ # class MyEngine < Engine
169
+ # def compile!() "My.compile(#{contents.inspect})"; end
170
+ # end
171
+ #
172
+ # register 'my', MyEngine
173
+ # end
174
+ #
175
+ module Sinatra::JstPages
176
+ class Engine
177
+ # ### name [attribute]
178
+ # The name of the template.
179
+ attr_reader :name
180
+
181
+ # ### file [attribute]
182
+ # The string path of the template file.
183
+ attr_reader :file
184
+
185
+ def initialize(name, file)
186
+ @name = name
187
+ @file = file
188
+ end
189
+
190
+ # ### contents [method]
191
+ # Returns the contents of the template file as a string.
192
+ def contents
193
+ File.read(@file)
194
+ end
195
+
196
+ def wrap_jst(name)
197
+ compiled_contents = contents
198
+ compiled_contents = yield if block_given?
199
+
200
+ <<JS.strip.gsub(/^ {12}/, '')
201
+ JST[#{name.inspect}] = function() {
202
+ if (!c[#{name.inspect}]) c[#{name.inspect}] = (#{compiled_contents});
203
+ return c[#{name.inspect}].apply(this, arguments);
204
+ };
205
+ JS
206
+ end
207
+
208
+ # ### function [method]
209
+ # The JavaScript function to invoke on the precompile'd object.
210
+ #
211
+ # What this returns should, in JavaScript, return a function that can be
212
+ # called with an object hash of the params to be passed onto the template.
213
+ def compile!
214
+ wrap_jst(name) do
215
+ "_.template(#{contents.inspect})"
216
+ end
217
+ end
218
+ end
219
+
220
+ class HamlEngine < Engine
221
+ def compile!
222
+ wrap_jst(name) do
223
+ "Haml(#{contents.inspect})";
224
+ end
225
+ end
226
+ end
227
+
228
+ class JadeEngine < Engine
229
+ def compile!
230
+ wrap_jst(name) do
231
+ "require('jade').compile(#{contents.inspect})"
232
+ end
233
+ end
234
+ end
235
+
236
+ class EcoEngine < Engine
237
+ def compile!
238
+ wrap_jst(name) do
239
+ "function() { var a = arguments.slice(); a.unshift(#{contents.inspect}); return eco.compile.apply(eco, a); }"
240
+ end
241
+ end
242
+ end
243
+
244
+ class HamlCoffeeEngine < Engine
245
+ def compile!
246
+ HamlCoffeeAssets.config.context = false
247
+ HamlCoffeeAssets::Compiler.compile(name, contents, true).
248
+ match(/^ window.JST(.*)\n };$/m)[0].gsub(/^ window.JST/, 'JST')
249
+ end
250
+ end
251
+
252
+ register 'tpl', Engine
253
+ register 'jst', Engine
254
+ register 'jade', JadeEngine
255
+ register 'haml', HamlEngine
256
+ register 'eco', EcoEngine
257
+
258
+ if defined?(HamlCoffeeAssets)
259
+ register 'hamlc', HamlCoffeeEngine
260
+ end
261
+ end